I have listview and it doesn't support image in second column. I try create ovalshape, but it olways is on the background of listview. So nobody can see it. I try ovalShape1.BringToFront();, but it doesn't work. Anybody can help me?
Here is a simple example with an external variable.
I assume you have added your images to an ImageList imageList1.
int imgIndex = 0;
private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
if (e.ColumnIndex == 1)
e.Graphics.DrawImage(imageList1.Images[imgIndex], e.Bounds);
else e.DrawDefault = true;
}
private void button1_Click(object sender, EventArgs e)
{
imgIndex++;
listView1.Invalidate();
}
You would more likely want to get the imageindex from data in the ListViewItem separately for each Row, maybe like this:
//..
e.Graphics.DrawImage(imageList1.Images[Convert.ToInt16( e.SubItem.Text) ], e.Bounds);
//..
As usual error checking is up to you.
Also note the Invalidate, which triggers the Paint and the subsequent DrawSubItem event, necessary after you have changed the imageindex. When the underlying values change, the system will take care of that.
Related
I have a huge problems every time I try to resize my columns and rows. I'm trying to autoresize the columns and the rows with the function:
dataGridView1.AutoResizeColumns();
dataGridView1.AutoResizeRows();
If i put this two lines after I pass the datasource to dataview, it doesn't work. I tried to handle the DataSourceBindingComplete, and idem it doesn't work. I tried to set it in the form.designer.cs and it doesn't work. then
I tried to make a button
private void button1_Click(object sender, EventArgs e)
{
dataGridView1.AutoResizeColumns();
dataGridView1.AutoResizeRows();
}
and when I click the button everything works perfectly!!! It resizes all my columns and my rows. But i don't want this. I want it automatic.
Can you guys help me please and explain why it does that? Doesn't make sense, inside the original code it doesn't work, but in a separate button it works.
This has worked for me.
Set AutoSizeColumnsMode and AutoSizeRowsMode values to AllCells from None in the designer.
Have you tried setting the DataGridViewAutoSizeColumnsMode before you set the source, if possible?
private void button1_Click(object sender, EventArgs e)
{
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
dataGridView1.DataSource = SourceList; // Your Collection here
dataGridView1.AutoResizeRows();
}
I apologize that it took me more than a year to see this post...
Here's what I did to make this "automatic".
private void AutoResizeGrid()
{
if (dataGridView.Columns.Count < 1) return;
dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
dataGridView.AutoResizeRows(DataGridViewAutoSizeRowsMode.DisplayedCells);
}
private void MatrixDataGridView_ClientSizeChanged(object sender, EventArgs e)
{
if (!this.Visible) return;
AutoResizeGrid();
}
private void MatrixDataGridView_Scroll(object sender, ScrollEventArgs e)
{
if (!this.Visible) return;
AutoResizeGrid();
}
Before adding this code, I went to the Designer and I set "AutoSizeColumnsMode" and "AutoSizeRowsMode" both to "DisplayedCells". This causes automation when the grid first receives the data. The code above causes automation when a resize or scroll event happens.
Ehm, umm, this means some lines should be two-lined in size. My boss think this is more simple solution, than limit displayed text to fit width and don't like horizontal scroll bar >_<
lst.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
lst.MeasureItem += lst_MeasureItem;
lst.DrawItem += lst_DrawItem;
private void lst_MeasureItem(object sender, MeasureItemEventArgs e)
{
e.ItemHeight = (int)e.Graphics.MeasureString(lst.Items[e.Index].ToString(), lst.Font, lst.Width).Height;
}
private void lst_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
e.DrawFocusRectangle();
e.Graphics.DrawString(lst.Items[e.Index].ToString(), e.Font, new SolidBrush(e.ForeColor), e.Bounds);
}
private void lst_MeasureItem(object sender, MeasureItemEventArgs e)
{
e.ItemHeight = (int)e.Graphics.MeasureString(lst.Items[e.Index].ToString(), lst.Font, lst.Width).Height;
}
private void lst_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
e.DrawFocusRectangle();
e.Graphics.DrawString(lst.Items[e.Index].ToString(), e.Font, new SolidBrush(e.ForeColor), e.Bounds);
}
To get the right display member to show up when data binding, replace
lst.Items[e.Index].ToString()
with a casted version of the property. So if your binding source is class object Car it would look like
((Car)lst.Items[e.Index]).YourDisplayProperty
Then the above functions can appropriately measure the string and draw it. :)
Helpful link
Check out this answer. It overrides the template of the listbox with a textblock which wraps the text. Hope it's useful. To solve your problem I think you shold add : ScrollViewer.HorizontalScrollBarVisibility="Disabled" . Found it here
To make binding correct, be sure to add check "lst.Items.Count > 0" to lst_MeasureItem function. Here is my example:
if (lst.Items.Count > 0)
{
e.ItemHeight = (int)e.Graphics.MeasureString(lst.Items[e.Index].ToString(), lst.Font, lst.Width).Height;
}
Everything else seems to work nicely after that.
I have created a DataGridView, one of the cells (DataGridViewTextBoxCell) I would like to have a background image. To do this I have used the following on the CellPainting event.
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
var image = Resources.item_qty_white;
e.PaintBackground(e.ClipBounds, false);
e.Graphics.DrawImageUnscaled(image, 1410, e.CellBounds.Top);
}
This works well and the image is on ever row in the position I want. However, the cell it is sitting in has a DataGridViewTextBoxCell with a numeric value. The image floats on top of this value and thus is hidden. I guess the ideal solution would be to make the DataGridViewTextBoxCell be "TopMost" but I couldn't figure out how to do this.
I then decided to try and make the background image partial transparent so the value underneath would be visual, so I changed my CellPainting code to below.
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
var image = Resources.item_qty_white;
e.PaintBackground(e.ClipBounds, false);
image.MakeTransparent(Color.White);
e.Graphics.DrawImageUnscaled(image, 1410, e.CellBounds.Top);
}
This again worked and I could see the value with the background image surrounding it as I would like. However the next issue arise when I tried to update the value of the cell. Once I did that the previous value was visible and the new value that I was trying to set was overlapping it. I am now stuck.
Any advice/guidance would be very appreciated.
You have to set e.Handled = true to prevent the system from painting. The below code works as you expected.
void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex != -1 && e.ColumnIndex == columnIndex)
{
if ((e.PaintParts & DataGridViewPaintParts.Background) != DataGridViewPaintParts.None)
{
e.Graphics.DrawImage(Resources.Image1, e.CellBounds);
}
if (!e.Handled)
{
e.Handled = true;
e.PaintContent(e.CellBounds);
}
}
}
I'm in the stages of making a program which will require a tabpage to flash when an event happens
I've googled around, and i came across this: Blink tab header on receiving event. This is similar, but uses WPF, and i'm using WinForms, and i'm not even sure that does what i want :L
I've also found this: C#: Flash Window in Taskbar via Win32 FlashWindowEx. This is what i want, but obvious for the whole form, and in the taskbar, not 'in form'
Anyone got any ideas?
I'm not saying this is the best way or even a great way to accomplish this, but it does work. I've used code similar to this when I needed to something similar.
The tabControl1 has two tabs and I blink tab 1 (the second tab).
For my example that I threw together, I set tabControl1's DrawMode property to "OwnerDrawFixed" and then a couple of buttons which start/stop the timer. The interval was something like 750ms but you could choose whatever, of course. On a timer1_Tick event, I swap out the current color and tell the tabControl1 to refresh itself. That'll make the DrawItem event get raised and then I either draw the rectangle the current color if it is tab page 1 or the backcolor if not. Then I draw the tabpage's text.
It works. Could use some tweaking for sure. Give it a whirl!
public partial class Form1 : Form
{
Color currentColor = Color.Green;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (currentColor == Color.Yellow)
currentColor = Color.Green;
else
currentColor = Color.Yellow;
tabControl1.Refresh();
}
private void button2_Click(object sender, EventArgs e)
{
timer1.Stop();
}
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
if (timer1.Enabled && e.Index == 1)
{
e.Graphics.FillRectangle(new SolidBrush(currentColor), e.Bounds);
}
else
{
e.Graphics.FillRectangle(new SolidBrush(this.BackColor), e.Bounds);
}
Rectangle paddedBounds = e.Bounds;
paddedBounds.Inflate(-2, -2);
e.Graphics.DrawString(tabControl1.TabPages[e.Index].Text, this.Font, SystemBrushes.HighlightText, paddedBounds);
}
}
hi all i'm trying to perform an action once the user double clicks on an item in the listview.
but there doesnt appear to be any methods available for this. can anybody please help me out here?
thanks lots :D
ANSWER (Thanks to Kyle's link):
private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (listView1.Items.Count >= 1)
Process.Start(listView1.SelectedItems[0].Text);
}
You could handle the doubleclick method of the ListView and then loop through each selected item. Something like:
private void thelistview_MouseDoubleClick(object sender, MouseEventArgs e)
{
foreach(ListViewItem item in thelistview.SelectedItems)
{
//do something with item
}
}
You also need to hook up the event unless you do it in the designer...
thelistview.MouseDoubleClick +=
new System.Windows.Forms.MouseEventHandler(this.thelistview_MouseDoubleClick);
Have a look at this blog. Should help you do what you want to.