Sorting Data in the Silverlight DataGrid


This post has been updated to work with the RTW version of the Silverlight 2 DataGrid.  The code examples are not guaranteed to work with previous Beta versions of the DataGrid. Read more about the features that the Silverlight 2 DataGrid has to offer…

Multi-column Sorting

One of the most requested features in Beta 1 was a way to sort the data contained in the DataGrid.  In fact it was so desired that clever developers such as Matt Berseth simply created their own implementation.  Fortunately, you no longer have to put much work into getting this functionality out of the box. 

To get sorting functionality in your DataGrid you will need to perform the following steps:

  1. Make sure that the collection that you use as the DataGrid’s ItemsSource implements IList.  Common implementations are List<T> and ObservableCollection<T>. 
  2. That’s it, you don’t need to do anything else

Why this odd requirement?  Under the covers, when a DataGrid is data bound to a collection that implements IList, it creates an internal ListCollectionView to provide the sorting functionality.  Since CollectionViews can handle multiple levels of sorting, the DataGrid also possesses this functionality and exposes it by allowing your users to click on multiple headers while holding the Shift key.

Here is the DataGrid showing off multi-column sorting:

 MultiColumnSort

Customizing Sorting

Alternatively if you want more control over how the sorting algorithm is performed, you can implement the ICollectionView interface currently found in System.Windows.Controls.Data.  The DataGrid knows that when it is bound to an implementation of ICollectionView that it should delegate all sorting to it, listening to its SortDescriptions collection and visually displaying the sorting status of the CollectionView.  Additionally by using an external CollectionView, you can have multiple controls share the same sort order.

Turning Off Sorting

It is easy to get sorting out of the box, but you might not want to allow your DataGrid or a particular column to be sorted by your user.  To turn this off, use DataGrid’s CanUserSortColumns property to turn on or off all sorting at the DataGrid level, or use DataGridColumn’s CanUserSort to turn on or off sorting for a particular column.

C#

dataGrid1.CanUserSortColumns = false;
unsortableColumn.CanUserSort = false;

VB

DataGrid1.CanUserSortColumns = False
UnsortableColumn.CanUserSort = False
Choosing Which Property to Sort By

Sometimes the property that your column is bound to is not always the one that you want it to sort by.  Normally a column sorts by the property that it is bound to through the Binding property.  However, if you look at the Template Column there is no Binding property, meaning that the DataGrid has no idea of how to sort the data if you were to click on that column’s header.  To give the DataGrid that information, you can use a property found on all column types called SortMemberPath.  This property allows you to specify a path to the property on the data item that you want that particular column to sort by.  Now if you create a template column that uses a DatePicker to allow your user to select a date instead of the standard TextBox, you can still provide sorting for that column by setting the SortMemberPath.

C#

datePickerColumn.SortMemberPath = "Birthday";

VB

DatePickerColumn.SortMemberPath = "Birthday"

Notice that since SortMemberPath is on DataGridColumn, you can use this beyond just template columns and can actually have a column bound to one property, but sort based on another property.  This is a much less common scenario, but becomes useful when working with types that normally don’t support sorting such as Colors or Images.

Sorting UI Cues

In the picture above you can see that each sorted column has an arrow in its header indicating if it is sorted ascending or descending.  It also has a subtle animation when switching between the two.  If you want to customize how this looks or behaves, the easiest way to do this is to use the Visual State Manager in Blend.  Otherwise, you can manually override the default DataGridColumnHeader template using the DataGrid.ColumnHeaderStyle property.  The template contains two storyboards, one named "SortAscending" and the other named "SortDescending".  These two storyboards are ran by the DataGrid when a column is sorted ascending or descending.  Finally there is a third storyboard called "Unsorted" that is ran when the data is no longer being sorted by that column and can be used to clean up any UI that you used to display sort status.

Comments (24)

  1. Lots of links again tonight: ToolTip Control by Martin Mihaylov, Scott Morrison(3) on DataGrid, VSM by

  2. Sergey Kogan says:

    One thing that always bothered me about sorting in standard microsoft grids is that once you sort a column there is no way to go back. Many times original "unsorted" order is very important.

    Conicidentally, our client asked us to implement this functionality and we did this with beta 1. You could click on a sorted column again and it would become unsorted.

    I hoped with beta 2 sorting I would be able to remove my sorting functionality and leave it to the grid. However, without ability to restore original order I cannot do it. Kinda, sucks.

    Any chance you could provide this ability?

  3. vesuvius says:

    I certainly hope that you can implement features like grouping like Matt does in his ASP.NET listview control. I’m currently using Windows Forms, you guys seem rather slow to release a WPF one (the commercial ones have been as slow as hell).

    We expect flexible grouping like Matt has shown (tree view +- cross, or a Vista TreeView or the WPF vista expander. We also need expect something like Mark Rideout’s tree grid view (check his blog), these are all features we are yelling out for.

    I really love the way this sorting is available out of the box. Please keep up the great work!

  4. kshaffar says:

    I want to preface this comment by saying that I am very excited about where you all are heading with Silverlight. THat being said…

    Have you guys done much load tesing on this feature?

    I did a simple protype where i put 100,000 rows into the grid.  When i try to sort this, my processor goes to 100% and it completely hangs the silverlight page.

    If i want to do a LOT of records, do i need to handle sorting myself?  

    Also when i have the 100K records the scrolling get a bit unresponsive. It is much better than in Beta 1 though.

    Is this something that you will address or am i doing something beyond the scope of what Silverlight is meant to provide?

  5. kshaffar says:

    Actually it looks like if i don’t have a lot of non unique data, it works ok.

    Slowness was perhaps caused by it trying to sort a lot of things that where identical…

  6. brauliod says:

    A sample explaining how to perform custom paging and sorting could be quite interesting (e.g.: get 50 page records via web service…).

  7. David Cater says:

    Is there any way to disable the ability to sort?  I’m creating a DataGrid that will always be sorted by an internal SortOrder value in the object bound to the DataGridRow.  The user will be able to drag rows around to change the row’s position within the SortOrder.  Therefore it’s important that I not allow them to sort by arbitrary columns.  I could retemplate the DataGridColumnHeader, I would imagine, but I’m hoping there’s a simpler way to disable the functionality.

  8. John Hauppa says:

    How about an example of how do disable the sorting if you don’t want the user to be able to sort the grid?

  9. IhorCo says:

    Sorting is great, but how can we disable it? 🙂

    We use pages to show data from server, so we implemented own sorting functionality to sort not only within one page and we want to disable standard sorting in datagrid.

  10. DXS says:

    Great job in Explaining the DataGrid.

    Thanks for your time and effort

  11. David says:

    Hi, I’m having issues simply trying to get my datagrid to display data bound to it. I can see the data in e.Result (pulled from a WCF service) as ObservableCollection<ServiceProxy.MyType>

    No error occurs, however I am presented with a blank datagrid.

    A sideline question, why is it that in a trace only the ‘PropertyChanged’ member is visible rather than allowing me to drill-down to the actual properties of my type?

    I tried to simplify things by taking my service & type out of the picture, so I defined the following directly in my Page.xaml.cs:

    class RachelsChickens

    {

       public string Something { get; set; }

       public int ANumber { get; set; }

       public bool IsRachelAWogBarbie { get; set; }

    }

    And in my Completed handler I replaced the use of e.Result with:

    List<RachelsChickens> wogs = new List<RachelsChickens>();

    wogs.Add(new RachelsChickens() { ANumber = 42, IsRachelAWogBarbie = true, Something = "baby smuggler" });

    wogs.Add(new RachelsChickens() { ANumber = 21, IsRachelAWogBarbie = false, Something = "alcomohol is evil" });

    dg.ItemsSource = wogs;

    With this in place, my datagrid generates the columns correctly & adds rows for each record, however there is NO DATA displayed in the rows.

    If you could provide any insight into these issues I’d greatly appreciate it! (I’m working with Version: 2.0.30523.8)

  12. David says:

    I think I know the reason for my main WCF data not loading; due to the fact that it is a linq2sql entity that obviously can’t be resolved by the silverlight client. I’m still puzzled as to why my simple List binding failed to display any data however, and I’d appreciate any thoughts getting the datagrid to work with linq2sql data loaded via a WCF service.

  13. As you might have heard , we just released Silverlight 2 , and with it the first version of the Silverlight

  14. Hi kshaffar,

    We have made performance improvements to both sorting as well as scrolling in the release version of the DataGrid.

    For those of you wondering how to turn off sorting, this functionality has been added through the CanUserSortColumns described above.

  15. Manish Dalal says:

    Are there any plan to provide developer to plug in custom sort functionality like WPF? This will be beneficial when binding to generic data containers. We are trying to build DataGrid dynamically and trying to binding to generic container that can be used to save and retrieve data using converter (this is due to lack of support of anonymous types). I am able to display and save data, but sort errors out. May be an example showing how to implement custom sorting will be helpful…

  16. Thanks for the feedback Manish,

    We are looking into that as something that we could possibly do in our next release.

    -Scott

  17. Cristi says:

    Thanks the article is great and the one on new datagrid rocks,

    I have one question… can I get the datagrid sorted automatically when I change the value of a field!? For example I have 3 column headers: IndexNumber, Title, Name, and two buttons Up and Down, on the event handler of the up button I change the indexNumber of the current selected row with the indexNumber of the row above. Will my datagrid update the UI automatically if is somehow set it to sort by indexNumber!?

  18. DJ Maquina says:

    Very good article … I really enjoyed it. I proposed the use of Silverlight at my office and they asked me about adding data grid functionality … thanks Gud … they really like the idea of Silverlight …

    … About Sergey’s commentary of recovering … It is actually a silly idea to ask about recovering … recovering could mean a lot of things … you just have to program it your self … you could, for instance, have an index that saves the last arrangement … so you can go back … this is a basic undo operation … thst wound be a waste of space either:

    1- if the list is small or medium (50 to 200 or 300)… is not so much space

    2 -if it is a large list (several thousands) use pages and you are back in the first case.

    Cheers

    mqn

  19. Firehead says:

    Hi Scott and other guys. Is there any ability to handle sorting event?

  20. Free Shoper says:

    Good, good, but how have this sorting with an updatable collection?

    this sort is not update on a PropertyChanged event come from an item list…

    http://silverlight.net/forums/p/54268/140247.aspx

  21. Dave says:

    So, how can we programmatically tell the DataGrid to sort by column X (in a way that renders the column as if the user had clicked it, with all appropriate glyphs)?

    <rant>Seems like this is obvious functionality that’s missing (which is my general beef with SL).</rant>

  22. Alex V says:

    I have grid and several columns that allow sorting. But I want to sort by one of these columns when my control is displayed at the first time.

  23. Rhinomerc says:

    Hi,

    Sorting is really really slow. Takes 4 seconds for a 25000 item collection.

    How can we improve this?