Partager via


WPF DataGrid: Tri-state Sorting sample

Here is a short sample on how to create a tri-state sorting experience with the WPF DataGrid. In the current design, when clicking on a column header it will toggle sorting of the column starting from ascending to descending. Unfortunately you cannot get back to the original state without adding your own custom logic for it. To get back to the original state you have to set the column.SortDirection back to null and clear out the SortDescriptions that were added when you click on the column header. In this sample I decided to add one more toggle state so when you click on the column header a third time it goes back to the original state. I’m adding this functionality to the DataGrid.Sorting event and stop the default sort if the toggle state is going back to the original state. Here is the code:       

private void DataGrid_Standard_Sorting(object sender, DataGridSortingEventArgs e)

{

  DataGrid dataGrid = sender as DataGrid;

  string sortPropertyName = Helpers.GetSortMemberPath(e.Column);

  if (!string.IsNullOrEmpty(sortPropertyName))

  {

    // sorting is cleared when the previous state is Descending

    if (e.Column.SortDirection.HasValue && e.Column.SortDirection.Value == ListSortDirection.Descending)

    {
int index = Helpers.FindSortDescription(dataGrid.Items.SortDescriptions, sortPropertyName);

      if (index != -1)

      {
  e.Column.SortDirection = null;

          // remove the sort description

          dataGrid.Items.SortDescriptions.RemoveAt(index);

          dataGrid.Items.Refresh();

          if ((Keyboard.Modifiers & ModifierKeys.Shift) != ModifierKeys.Shift)

          {
  // clear any other sort descriptions for the multisorting case

           dataGrid.Items.SortDescriptions.Clear();

           dataGrid.Items.Refresh();
}

          // stop the default sort

          e.Handled = true;

      }
}
}

}

 

I also decided to add some extra functionality for displaying the sort order of the column when doing multi-column sorting. By default when you do multi-column sorting you really have no idea which column is sorted in which order as it only shows that direction triangle. I just add text to the header but you can always get creative and add all that WPF eye candy. Here is a screenshot:

sortingOrder

The full sample is here.

Other DataGrid Samples:

ScrollViewer with ToolTip

Custom sorting, column selection, single-click editing

Styling rows and columns based on header conditions

Clipboard Copy

DataGrid_V1_TriStateSortingSample.zip

Comments

  • Anonymous
    August 29, 2008
    PingBack from http://informationsfunnywallpaper.cn/?p=2939

  • Anonymous
    August 29, 2008
    Overview The DataGrid uses a set of DataGridColumns to describe how to display its data just like a GridView

  • Anonymous
    August 29, 2008
    If you haven’t already, you can download the binaries and source for the DataGrid here . DataGridComboBoxColumn

  • Anonymous
    September 01, 2008
    The comment has been removed

  • Anonymous
    September 02, 2008
    _gdc, In my example I am getting the view from the ItemsSource and expect a ListCollectionView.  Since you have changed it to IEnumerable<T> it is no longer a ListCollectionView.  In the constructor of my sample, try removing the lines related to getting the CollectionViewSource.  It should work after that. -Vince

  • Anonymous
    September 07, 2008
    Started playing with the Datagrid in a WPF app runing on a desktop. I have notice that when I drag the scroll button on some machines, there is a pretty chunky lag. The content redraw updates in a unpleasant, laggy way. There were only 500 items in the grid...

  • Anonymous
    September 08, 2008
    Karl, Would you mind posting the specs for the machine that you find that it is lagging. Thanks, Vince

  • Anonymous
    September 08, 2008
    Opps never mind. Scrolling works fine. The issue is that if I set my ItemSource to an custom ObservableCollection<T> T must define a public string property named "Id" or the binding will throw a bad path and silently swallow the exception on all the rows. Which absolutely kills the performance of scroll.... You get this in the output window of the debugger. System.Windows.Data Error: 39 : BindingExpression path error: 'Id' property not found on 'object' ''RowProxy' (HashCode=11295760)'. BindingExpression:Path=Id; DataItem='RowProxy' (HashCode=11295760); target element is 'DataGridRow' (Name=''); target property is 'Header' (type 'Object')

  • Anonymous
    September 15, 2008
    Hi Vincent! Will you be so kind and help me with a following scenario? =) Imagine I have a DataGrid bound with ObservableCollection. I want to prevent user from editing existing rows and enable only to add new rows and edit'em right in a place or delete new or existing rows. How can I achieve such a scenario? Best regards, RobertT

  • Anonymous
    September 16, 2008
    RobertT, One possible solution is to listen to the DataGrid.BeginningEdit event and cancel the BeginEdit if the row they are trying to edit is an existing row.  Deleting is a separate operation so it will work as normal with this solution.

  • Anonymous
    September 16, 2008
    As you might have heard, .NET Framework 3.5 SP1 and Visual Studio 2008 SP1 are out today! There are a

  • Anonymous
    September 19, 2008
    In the v1 release (and CTP) of the WPF DataGrid there will be support for Clipboard.Copy but no support

  • Anonymous
    December 03, 2008
    Hi, can v populate DataGrid dynamically. If yes, can u post a sample on the same using DataGridTextColumn() and DataGridRow() (similar to how we add in DataTable) Or is there other way of doing it cos am stuck with it. Thanks in Advance.

  • Anonymous
    December 18, 2008
    Priya, DataGrid can be populated dynamically, but not isn the same way as the DataTable.  The DataGrid is bound to an ItemsSource so as items are added and removed the DataGrid will update as necessary.  Could you expand on your scenario a bit and hopefully I can provide further assistance.

  • Anonymous
    November 11, 2009
    Hello,  I am using WPF toolokit's data grid, and inthat grid I have a column for checkbox which I add as below: <toolkit:DataGridTemplateColumn >                        <toolkit:DataGridTemplateColumn.CellTemplate>                            <DataTemplate>                                <CheckBox Click="OnUsedClicked"                                          IsChecked="{Binding Path=Used}"                                         />                            </DataTemplate>                        </toolkit:DataGridTemplateColumn.CellTemplate>                    </toolkit:DataGridTemplateColumn> I would like to sort on all columns of my grid, so to the grid defination I added CanUserSortColumns="True"  to my grid. On doing this the rest of the columns get sorted but not the checkbox column.By checkbox column sorting I mean that all checked boxes(rows) to be together and all unchecked boxes(rows) to be together. I do understand there might be multiple checked so what basis needs to be used, I have a time column , I can use that along with it. i.e sorting on Checkbox + Time this would lead to all say unchecked together , based on time as the second parameter. I am not sure if this is possible, if yes how? Regards Barti I would like that

  • Anonymous
    January 14, 2010
    I'm curious how to shrink the column back to its original size after the sort description is removed.  For example, click the Cake column 3 times.  When the header goes back to "Cake", the column doesn't shrink. Thanks for a super helpful blogpost.