106

How can I set the column width of a c# winforms listview control to auto. Something like width = -1 / -2 ?

Majid
  • 13,853
  • 15
  • 77
  • 113
Kai
  • 5,850
  • 13
  • 43
  • 63

11 Answers11

123

You gave the answer: -2 will autosize the column to the length of the text in the column header, -1 will autosize to the longest item in the column. All according to MSDN. Note though that in the case of -1, you will need to set the column width after adding the item(s). So if you add a new item, you will also need to assign the width property of the column (or columns) that you want to autosize according to data in ListView control.

Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
  • 1
    Note that while the MSDN article references ColumnHeader, that does just mean the column. Code example: `myListView.Columns[0].Width = -1;` – Eric G Jun 05 '19 at 19:27
115

Use this:

yourListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);

yourListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);

from here

Majid
  • 13,853
  • 15
  • 77
  • 113
  • 11
    But what if you want the maximum of the header or the data width? With no flicker? – toddmo Sep 03 '14 at 20:56
  • 1
    @toddmo Use both strings. And, if neccesary, between listView.BeginUpdate(); ... listView.EndUpdate(); – Artem Zh. Dec 05 '18 at 12:13
  • 1
    Can't use both simultaneously. If attempt to "or" together `ColumnHeaderAutoResizeStyle.ColumnContent` and `ColumnHeaderAutoResizeStyle.HeaderSize` (resulting in a value of "3"), at runtime that line gives exception *"System.ComponentModel.InvalidEnumArgumentException: 'The value of argument 'headerAutoResize' (3) is invalid for Enum type 'ColumnHeaderAutoResizeStyle'. Parameter name: headerAutoResize' "*. Alternatively, if you execute both those lines, the second one will overwrite the first value, as if the first line was not there. – ToolmakerSteve May 29 '21 at 01:18
26

I made a program that cleared and refilled my listview multiple times. For some reason whenever I added columns with width = -2 I encountered a problem with the first column being way too long. What I did to fix this was create this method.

private void ResizeListViewColumns(ListView lv)
{
    foreach(ColumnHeader column in lv.Columns)
    {
        column.Width = -2;
    }
}

The great thing about this method is that you can pretty much put this anywhere to resize all your columns. Just pass in your ListView.

Majid
  • 13,853
  • 15
  • 77
  • 113
Jimmy Campbell
  • 261
  • 3
  • 2
  • 1
    this will set the width to the width of the last item in your ListView – Qsiris Aug 16 '12 at 14:55
  • I use your code but if I have only one column in my listview, each time I get a horizontal scrollbar. If there are at least two columns the code works well. Do you know where does this behaviour come from? – prototype0815 Aug 30 '17 at 12:04
6

You can use something like this, passing the ListView you want in param

    private void AutoSizeColumnList(ListView listView)
    {
        //Prevents flickering
        listView.BeginUpdate();

        Dictionary<int, int> columnSize = new Dictionary<int,int>();

        //Auto size using header
        listView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);

        //Grab column size based on header
        foreach(ColumnHeader colHeader in listView.Columns )
            columnSize.Add(colHeader.Index, colHeader.Width);

        //Auto size using data
        listView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);

        //Grab comumn size based on data and set max width
        foreach (ColumnHeader colHeader in listView.Columns)
        {
            int nColWidth;
            if (columnSize.TryGetValue(colHeader.Index, out nColWidth))
                colHeader.Width = Math.Max(nColWidth, colHeader.Width);
            else
                //Default to 50
                colHeader.Width = Math.Max(50, colHeader.Width);
        }

        listView.EndUpdate();
    }
Nickyboy
  • 124
  • 1
  • 3
  • This worked a treat! – Ocean Airdrop May 24 '22 at 09:28
  • Doesn't seem to work on `AfterLabelEdit`, since the layout refresh is only done after the call because the event contains a `CancelEdit` property. No idea how to work around that. – Nyerguds Jul 25 '23 at 07:34
  • Seems it can be fixed simply by explicitly setting `listView.Items[e.Item].Text = e.Label` in the `AfterLabelEdit` code. Obviously any column autosizing code is only called in the case the `CancelEdit` was not set anyway. – Nyerguds Jul 25 '23 at 08:35
5

There is another useful method called AutoResizeColumn which allows you to auto size a specific column with the required parameter.

You can call it like this:

listview1.AutoResizeColumn(1, ColumnHeaderAutoResizeStyle.ColumnContent);
listview1.AutoResizeColumn(2, ColumnHeaderAutoResizeStyle.ColumnContent);
listview1.AutoResizeColumn(3, ColumnHeaderAutoResizeStyle.HeaderSize);
listview1.AutoResizeColumn(4, ColumnHeaderAutoResizeStyle.HeaderSize);
Fütemire
  • 1,705
  • 1
  • 26
  • 21
David Silva-Barrera
  • 1,006
  • 8
  • 12
3

If you have ListView in any Parent panel (ListView dock fill), you can use simply method...

private void ListViewHeaderWidth() {
        int HeaderWidth = (listViewInfo.Parent.Width - 2) / listViewInfo.Columns.Count;
        foreach (ColumnHeader header in listViewInfo.Columns)
        {
            header.Width = HeaderWidth;
        }
    }
2

Expanding a bit on Fredrik's answer, if you want to set the column's auto-resize width on the fly for example: setting the first column's auto-size width to 70:

myListView.Columns[0].AutoResize(ColumnHeaderAutoResizeStyle.None);
myListView.Columns[0].Width = 70;
myListView.Columns[0].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
Majid
  • 13,853
  • 15
  • 77
  • 113
Joe
  • 91
  • 2
  • 2
1

This solution will first resize the columns based on column data, if the resized width is smaller than header size, it will resize columns to at least fit the header. This is a pretty ugly solution, but it works.

lstContacts.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
colFirstName.Width = (colFirstName.Width < 60 ? 60 : colFirstName.Width);
colLastName.Width = (colLastName.Width < 61 ? 61 : colLastName.Width);
colPhoneNumber.Width = (colPhoneNumber.Width < 81 ? 81 : colPhoneNumber.Width);
colEmail.Width = (colEmail.Width < 40 ? 40 : colEmail.Width);

lstContacts is the ListView. colFirstName is a column, where 60 is the width required to fit the title. Etc.

1

It is also worth noting that ListView may not display as expected without first changing the property:

myListView.View = View.Details; // or View.List

For me Visual Studio seems to default it to View.LargeIcon for some reason so nothing appears until it is changed.

Complete code to show a single column in a ListView and allow space for a vertical scroll bar.

lisSerials.Items.Clear();
lisSerials.View = View.Details;
lisSerials.FullRowSelect = true;

// add column if not already present
if(lisSerials.Columns.Count==0)
{
    int vw = SystemInformation.VerticalScrollBarWidth;
    lisSerials.Columns.Add("Serial Numbers", lisSerials.Width-vw-5);
}

foreach (string s in stringArray)
{
    ListViewItem lvi = new ListViewItem(new string[] { s });
    lisSerials.Items.Add(lvi);
}
tonyb
  • 379
  • 2
  • 6
0

I believe the author was looking for an equivalent method via the IDE that would generate the code behind and make sure all parameters were in place, etc. Found this from MS:

Creating Event Handlers on the Windows Forms Designer

Coming from a VB background myself, this is what I was looking for, here is the brief version for the click adverse:

  1. Click the form or control that you want to create an event handler for.
  2. In the Properties window, click the Events button
  3. In the list of available events, click the event that you want to create an event handler for.
  4. In the box to the right of the event name, type the name of the handler and press ENTER
Jason
  • 297
  • 3
  • 11
0

I couldn't find a proper code so I decided to write it myself. Here you can use it.

public static int AutoResizeColumnEX_Value = 0;

public static void AutoResizeColumnEX(this ListView listView, int columnIndex)
{
    if (columnIndex != (listView.Columns.Count - 1))
    {
        var orginalEndColumnWidth = listView.Columns[listView.Columns.Count - 1].Width;

        listView.AutoResizeColumn(listView.Columns.Count - 1, ColumnHeaderAutoResizeStyle.ColumnContent);
        listView.AutoResizeColumn(listView.Columns.Count - 1, ColumnHeaderAutoResizeStyle.HeaderSize);

        if (orginalEndColumnWidth < listView.Columns[listView.Columns.Count - 1].Width)
        {
            AutoResizeColumnEX_Value = listView.Columns[listView.Columns.Count - 1].Width - orginalEndColumnWidth;

            listView.Columns[columnIndex].Width += AutoResizeColumnEX_Value;
            listView.Columns[listView.Columns.Count - 1].Width = orginalEndColumnWidth;
        }
        else
        {
            listView.Columns[columnIndex].Width -= AutoResizeColumnEX_Value;
            listView.Columns[listView.Columns.Count - 1].Width = orginalEndColumnWidth;
        }
    }
    else
    {
        listView.AutoResizeColumn(columnIndex, ColumnHeaderAutoResizeStyle.ColumnContent);
        listView.AutoResizeColumn(columnIndex, ColumnHeaderAutoResizeStyle.HeaderSize);
    }
}
starball
  • 20,030
  • 7
  • 43
  • 238
Keashe
  • 1