Listview Column Header AutoSize & column sorting

E

Ed Kramer

Being doing a little UI work in vs 2008 and I noticed something. After
reading over the docs for the listview control it seems to me that some
things are missing.

I'd created a listview for my own use back in vs 2003 that implemented these
two things, to my surprise nobody has added them to the regular listview
control in 2008's version of visual studio.

First would be autosizing on column headers. Why is there no option to
autosize on 'Whichever is widest' either the column content or the column
header. If you have a wide header, but only a few short items and you sort on
ColumnHeaderAutoResizeStyle.ColumnContent you end up with columns you can't
read the headers on. If you instead resize to HeaderSize you end up with
perfect headers, but if you add an item with text longer than the header
you're still stuck at header size.

As a bit of a hack you can iterate through the columns and call
..AutoResize(ColumnContent) and then .AutoResize(HeaderSize) and compare the
widths and decide which one is bigger. But I imagine doing that is resource
intensive if you have a lot of columns. There appears to be no call you can
make on the listview or it's column header to get the width of the widest
item in a column so you can compare it to the header size and set this up
without doing some win32 API calls.

for (int index = 0; index < listView.Columns.Count;
index++)
{
ColumnHeader header = listView.Columns[index];

// HACK - We want the column headers to be the widh
of either the
// widest item in the column OR the header whichever
is wider.
// I have found no way to do this with the control
itself so
// I am doing the hack below.


header.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
contentWidth = header.Width;


header.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
headerWidth = header.Width;

if (contentWidth > headerWidth)
headerResize =
ColumnHeaderAutoResizeStyle.ColumnContent;
else
headerResize =
ColumnHeaderAutoResizeStyle.HeaderSize;

header.AutoResize(headerResize);
}

The other item was sorting by a column when you click on the header. The
control has a property for a ListViewItemSorter. But when you click on the
listview's columns nothing happens unless you specifically set up the sorter,
create an event handler for the ColumnClick event for the listview and do a
little voodoo hackery inside it to switch the sort order from Ascending to
Descending.


private void itemList_ColumnClick(object sender,
ColumnClickEventArgs e)
{
ListView listView = (ListView)sender;
ListViewItemSorter sorter = (ListViewItemSorter)
listView.ListViewItemSorter;

sorter.SortColumn = e.Column;
if (sorter.Order == SortOrder.Ascending)
sorter.Order = SortOrder.Descending;
else
sorter.Order = SortOrder.Ascending;

listView.Sort();
}


I like being able to create my own listviewitemsorter and use it, but
shouldn't there be a built in way to sort?

Is there no automatic way to do these two very useful functions without a
bunch of extra plumbing? Sure you can create your own listview with the extra
features and inherit from ListView as a base. But they really should be
included with the control out of the box.
 
J

Jeff Gaines

I like being able to create my own listviewitemsorter and use it, but
shouldn't there be a built in way to sort?

There is a crude in-built sorter which will sort column 1 either ascending
or descending - turn it on with the sorting property.

You are much better off rolling your own to take account of the different
data types the LV may contain, you can also use it to set the sort icons.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top