Monday, September 3, 2007

Optimal size of column headers in listview

When using a ListView in C# and the View property is set to View.Details, you probably want to set the width of the columns in the listview to an optimal size, without any … in the columns.

If the column text strings does not fit the column width (set at design time), three dots (...) will be displayed at run time, as shown below.

Display the text fully in the column, and get rid of the ...


For one moment, you may think of finding the length of the longest string in the column and assign it to the width of the column header. But wait, the length would be in terms of number of characters, whereas the width of the column should be in pixels. So, this will not work, unless you use a utility function to convert the length of the text (taking into consideration the font being used) and calculate it in terms of pixel. Yes it is possible :-) but you won't see it in this post!

Correct Solution
At runtime, set the Width of the ColumnHeader to:

a) -1 to adjust the width of the longest item in the column (without taking into consideration the column heading).

hdrCountry.Width = -1;
hdrName.Width = -1;

Now, the text in the columns is displayed correctly, but not the heading of the first column.

b) -2 to autosize width of the column, taking into consideration the column heading.

hdrCountry.Width = -2;
hdrName.Width = -2;

Now, it works fine. Hope it helps.


ashvin said...

To resize the last column to the optimal width, here is an interesting link:

The code:
protected override void WndProc( ref Message message )
const int WM_PAINT = 0xf ;

// if the control is in details view mode and columns
// have been added, then intercept the WM_PAINT message
// and reset the last column width to fill the list view
switch ( message.Msg )
case WM_PAINT:
if ( this.View == View.Details && this.Columns.Count > 0 )
this.Columns[this.Columns.Count - 1].Width = -2 ;
break ;

// pass messages on to the base control for processing
base.WndProc( ref message ) ;

ashvin said...