14

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 listview will resize and fit to winforms as winforms maximized but the columns you have designed on it which is not resize with listview.

My question is : Is there any way to resize the columns of listview with listview to fit winform size?.

Listview Design Code:

 private void Form1_Load(object sender, EventArgs e)
    {

        listView1.View = View.Details;
        listView1.LabelEdit = true;
        listView1.BackColor = Color.GreenYellow;
        listView1.Columns.Add("Date", 100, HorizontalAlignment.Left);
        listView1.Columns.Add("TransID", 50, HorizontalAlignment.Left);
        listView1.Columns.Add("voucher", 100, HorizontalAlignment.Right);
        listView1.Columns.Add("particulars", 300, HorizontalAlignment.Left);
        listView1.Columns.Add("deposit", 100, HorizontalAlignment.Right);
        listView1.Columns.Add("withdrawal", 100, HorizontalAlignment.Right);

        string connstr = "server=.;initial catalog=DataBase;uid=UID;pwd=PWD";
        SqlConnection con = new SqlConnection(connstr);
        con.Open();
        listView1.Items.Clear();
        listView1.Refresh();
        string sql = "select date=convert(varchar,date,103),transID,max(particulars)as particulars,sum(deposit)as deposit,sum(withdrawal) as withdrawal,voucher from debank group by date,transID,voucher";
        SqlCommand cmd = new SqlCommand(sql, con);
        SqlDataAdapter dap = new SqlDataAdapter(cmd);
        DataSet ds = new DataSet();
        dap.Fill(ds);
        DataTable dt = ds.Tables[0];

        for (int i = 0; i < dt.Rows.Count; i++)
        {
            DataRow dr = dt.Rows[i];
            ListViewItem lvi = new ListViewItem(dr["date"].ToString());
            lvi.SubItems.Add(dr["transID"].ToString());
            lvi.SubItems.Add(dr["voucher"].ToString());
            lvi.SubItems.Add(dr["particulars"].ToString());
            lvi.SubItems.Add(dr["deposit"].ToString());
            lvi.SubItems.Add(dr["withdrawal"].ToString());
            listView1.Items.Add(lvi);
            listView1.FullRowSelect = true;

        }

        SizeLastColumn(listView1);


    }
mahesh
  • 1,370
  • 9
  • 36
  • 61

5 Answers5

30
  1. Programatic one. You'll have to maintain it in code.
  2. You can adjust last column size in your listview so that it would be automatically resized. Net sample:

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;
}
elady
  • 535
  • 6
  • 22
Sasha Reminnyi
  • 3,442
  • 2
  • 23
  • 27
  • @LexRema, I have edited my question with Listview Design. Your code sort the problem of resize but rest of four previous columns and last columns keep long distance between them. – mahesh Jan 26 '11 at 09:45
  • @LexRema, How to solve the rest of four previous columns distance problem?. – mahesh Jan 26 '11 at 09:57
  • @LexRema, I have pass the value on form1_Resize EventHandller is : int x=Listview.Width/15 and thanafter like Listview1.columns[0]=x*2; it's throw compilling error Like"property indxercolumnheadercollection it is readonly" something like – mahesh Jan 26 '11 at 11:35
  • @LexRema, No still last column distance is too far from rest of previous five columns. can u provide me calculation of listview width – mahesh Jan 26 '11 at 11:57
  • Here I've added SizeLastColumn implementation that will do everything. – Sasha Reminnyi Jan 26 '11 at 12:03
  • @LexRema, Yes Now it is works but little problem in code that you have to edit listview to listview1. and other thing which is i not understand why? this code :0 ? 1 : ListView.Width/15; is needed it will do whithout it. – mahesh Jan 26 '11 at 14:11
  • If it works I would be greatful if you accept my answer as correct. That operator makes size in case the listview is wery small (width less than 15 px). But you can omit that operation. – Sasha Reminnyi Jan 26 '11 at 14:16
13

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);
    }
}
Raphael Smit
  • 652
  • 6
  • 11
HuseyinUslu
  • 4,094
  • 5
  • 33
  • 50
5

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;
}
Søren L. Fog
  • 359
  • 5
  • 4
1

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.

Community
  • 1
  • 1
Denis Palnitsky
  • 18,267
  • 14
  • 46
  • 55
0

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

aex
  • 85
  • 1
  • 9