Pages Menu
TwitterRssFacebook

Posted by on Jan 26, 2012 in Development

WPF: Sorting GridView Columns by Clicking Headers

WPF: Sorting GridView Columns by Clicking Headers

Recently, I was doing something in WPF where I had a table of data to output. According to my book, the ListView ships with a concrete ViewBase class, called GridView, which looks pretty much like the ‘normal’ Window data grid experience.

It was pretty trivial to add in, and takes the format, roughly, of:

   <ListView x:Name="MyList" MaxHeight="300" ItemsSource="{Binding}">
                    <ListView.View>
                        <GridView>
                            <GridViewColumn Header="Name" DisplayMemberBinding="{Binding FullName}"/>
                            <GridViewColumn Header="Hair Colour" DisplayMemberBinding="{Binding HairColour}"/>
                            <GridViewColumn Header="Eye Colour" DisplayMemberBinding="{Binding EyeColour}"/>
                         </GridView>
					</ListView.View>
    </ListView>

So far, so good. I mean, it works pretty much exactly as you would expect it to.

During testing, it came out that it would be handy to be able to sort the grid by clicking on the columns, as you’d be used to do in Windows Explorer. I didn’t think this would be a big deal. In Windows Forms it’s a built-in feature, it happens automagically. However, I couldn’t find an equivalent in the WPF control.

I did find a MSDN article – How to: Sort a GridView Column When a Header Is Clicked – which describes how to attach a click event to the column header click, work out what needs to be done, and sort the results. I made a couple of changes, for instance, I rewrote the Sort function, arguably making it less generic, but much more readable, by adding a SortDescription directly to the ListView control. (In fact, I only did this because I thought it was causing the problems below. I’m pretty sure it would have been find if I’d left it alone.)

Photo by PhotoJonny

Something wasn’t right though. The event was firing, the code looked like it was working, but the list was either getting sorted in a seemingly random fashion, or not at all when I clicked it.

It took me quite a long time to work out why, because there were no errors, and the event always got called, even when it didn’t seem like it was doing anything.

Also, I guess I was a bit blinded by my faith in the MSDN code sample. Eventually, I saw the problem in the sample:

string header = headerClicked.Column.Header as string;
Sort(header, direction);

The list is being sorted by assuming that the column header is the same as the binding source property name.

That’s quite an assumption, and I do think MSDN could have called it out better. It works in their simplistic example (column names of Month,Day,Year) but silently stops working for anything more complicated. It’s also why the list was either being sorted randomly (because you’re sorting by something that doesn’t exist) or not at all (once you’ve sorted it randomly once, you’re just repeating yourself).

Anyway, it’s fairly simple to fix, because you can still get at the real binding value, with something like this:

string header =((Binding)headerClicked.Column.DisplayMemberBinding).Path.Path;
Sort(header, direction);

With that in place, clicking on the headers now works fine.

Written by Tom Morgan

Tom is a Microsoft Teams Platform developer and Microsoft MVP who has been blogging for over a decade. Find out more.
Buy the book: Building and Developing Apps & Bots for Microsoft Teams. Now available to purchase online with free updates.

Post a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.