I have face resize problem of listview columns. If you anchor/docking the listview to normal winform than the listview anchor or docking works well. I mean lis
You can resize columns by content as described here or you have to listen for Resize event of a ListView and set size of columns in runtime.
Here's my solution;
Instead of resize event I prefer resizeEnd of form, so that the code will run only once when the resize is complete.
private void Form1_ResizeEnd(object sender, EventArgs e)
{
this.ResizeColumnHeaders();
}
The ResizeColumnHeaders function sets all columns except the last one to fit against column-content. The last column will be using the magic-value hinted by LexRema.
private void ResizeColumnHeaders()
{
for (int i = 0; i < this.listView.Columns.Count - 1;i++ ) this.listView.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent);
this.listView.Columns[this.listView.Columns.Count - 1].Width = -2;
}
Also don't forget to call ResizeColumnHeaders() after you load your initial data;
private void Form1_Load(object sender, EventArgs e)
{
this.LoadEntries();
this.ResizeColumnHeaders();
}
One more thing is to prevent flickering while columns-resizes, you need to double-buffer the listview.
public Form1()
{
InitializeComponent();
this.listView.DoubleBuffer();
}
DoubleBuffer() is actually an extension for easy use.
public static class ControlExtensions
{
public static void DoubleBuffer(this Control control)
{
// http://stackoverflow.com/questions/76993/how-to-double-buffer-net-controls-on-a-form/77233#77233
// Taxes: Remote Desktop Connection and painting: http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
if (System.Windows.Forms.SystemInformation.TerminalServerSession) return;
System.Reflection.PropertyInfo dbProp = typeof(System.Windows.Forms.Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
dbProp.SetValue(control, true, null);
}
}
use this
Private Sub ListView1_Resize(sender As Object, e As EventArgs) Handles ListView1.Resize
Dim k = ListView1.Width - 10
Dim i = k / 3
ListView1.Columns(0).Width = k - i
ListView1.Columns(1).Width = i / 2
ListView1.Columns(2).Width = i / 2
End Sub
three columns one bigger two smaller with same size
A simple solution that takes a listview and the index of the column you want to resize automatically, so that the size of the entire listview's client area is utilized to the last pixel, no more and no less, i.e. no ugly horizontal scrollbar appearing even if resizing makes the control smaller.
You want to call this method from your Resize event handler, and also after adding an element in case a vertical scrollbar appeared after adding more lines than the control has room for vertically.
I disagree with the idea to react on the ResizeEnd event instead, as mentioned in one of the other posts, since this does not look nice on the screen if Windows is set up to draw windows while moving and resizing. The calculation is quick, so it doesn't create any problems to resize continuously.
static private void ResizeAutoSizeColumn(ListView listView, int autoSizeColumnIndex)
{
// Do some rudimentary (parameter) validation.
if (listView == null) throw new ArgumentNullException("listView");
if (listView.View != View.Details || listView.Columns.Count <= 0 || autoSizeColumnIndex < 0) return;
if (autoSizeColumnIndex >= listView.Columns.Count)
throw new IndexOutOfRangeException("Parameter autoSizeColumnIndex is outside the range of column indices in the ListView.");
// Sum up the width of all columns except the auto-resizing one.
int otherColumnsWidth = 0;
foreach (ColumnHeader header in listView.Columns)
if (header.Index != autoSizeColumnIndex)
otherColumnsWidth += header.Width;
// Calculate the (possibly) new width of the auto-resizable column.
int autoSizeColumnWidth = listView.ClientRectangle.Width - otherColumnsWidth;
// Finally set the new width of the auto-resizing column, if it has changed.
if (listView.Columns[autoSizeColumnIndex].Width != autoSizeColumnWidth)
listView.Columns[autoSizeColumnIndex].Width = autoSizeColumnWidth;
}
In a ListView control, with the View property set to Details, you can create a multi-column output. Sometimes you will want the last column of the ListView to size itself to take up all remaining space. You can do this by setting the column width to the magic value -2.
In the following example, the name of the ListView control is lvSample:
[c#]
private void Form1_Load(object sender, System.EventArgs e)
{
SizeLastColumn(lvSample);
}
private void listView1_Resize(object sender, System.EventArgs e)
{
SizeLastColumn((ListView) sender);
}
private void SizeLastColumn(ListView lv)
{
lv.Columns[lv.Columns.Count - 1].Width = -2;
}
EDIT:
Programaticaly you can do that with own implemented algorithm. The problem is that the list view does not know what of the columns you would like to resize and what not. So you'll have in the resize method (or in resizeEmd method) to specify all the columns size change. So you calculate all the width of the listview then proportionaly divide the value between all columns.
Your columns width is multiple to 50. So you have the whole listview width of 15*х (x=50 in default state. I calculated 15 value based on number of your columns and their width) conventional units. When the form is resized, you can calculate new x = ListView.Width/15
and then set each column width to needed value, so
private void SizeLastColumn(ListView lv)
{
int x = lv.Width/15 == 0 ? 1 : lv.Width/15;
lv.Columns[0].Width = x*2;
lv.Columns[1].Width = x;
lv.Columns[2].Width = x*2;
lv.Columns[3].Width = x*6;
lv.Columns[4].Width = x*2;
lv.Columns[5].Width = x*2;
}