Home » Blog

rounded header

Sorting and grouping in the WPF Property Grid

The Windows Forms property grid control has a PropertySort property which determines whether entries are sorted alphabetically, grouped by category, or both. The WPF Property Grid has no equivalent to this. So how does the WPF Property Grid support sorting and grouping?

The WPF Property Grid accesses its rows via the BindingView collection property. This sounds pretty innocent, but where there’s a data-bound collection in WPF, there’s a collection view, and that means that external code can apply whatever sorting, filtering and grouping it requires. This might be limited to alphabetical sorting and category grouping, or it might be something more application-specific.

Here’s how to reproduce the Windows Forms behaviour:

private static void Sort(PropertyGrid grid)
{
  SortDescription alphabetical = new SortDescription("Node.HumanName", ListSortDirection.Ascending);
  ICollectionView view = CollectionViewSource.GetDefaultView(grid.BindingView);
  view.SortDescriptions.Add(alphabetical);
}
 
private static void Group(PropertyGrid grid)
{
  PropertyGroupDescription byCategory = new PropertyGroupDescription("Node", new NodeToCategoryConverter());
  ICollectionView view = CollectionViewSource.GetDefaultView(grid.BindingView);
  view.GroupDescriptions.Add(byCategory);
}

If this is all you want, you don’t need to write the code yourself: the IsToolBarVisible property displays a toolbar which the user can use to sort and group the grid. (If you want to use CategoryAttribute-based grouping, but don’t want to use the standard toolbar, you can still use the NodeToCategoryConverter in your own grouping code; it’s a public part of the WPF Property Grid API.)

If you need customised sorting or grouping, then this code can serve as a starting point. For example, if you’re presenting a dictionary of values (or an object with many properties which don’t have the CategoryAttribute), you could group them by the first letter of the name as follows:

public class FirstLetterConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    Node node = (Node)value;
    return node.HumanName.Substring(0, 1).ToUpper();
  }
 
  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}
 
public partial class MyWindow : Window
{
  private static void GroupByFirstLetter(PropertyGrid grid)
  {
    SortDescription sorter = new SortDescription("Node.HumanName", ListSortDirection.Ascending);
    grid.BindingView.DefaultView.SortDescriptions.Add(sorter);
 
    PropertyGroupDescription grouper = new PropertyGroupDescription("Node", new FirstLetterConverter());
    grid.BindingView.DefaultView.GroupDescriptions.Add(grouper);
  }
}

Here’s the result:

Screenshot of a property grid grouped by first letter

The main thing to notice is that your SortDescriptions and GroupDescriptions will be applied to the elements of the BindingView class, which are of type PropertyGridRow, so you’ll typically refer to the Node property in your sorting and grouping expressions. From here you can look at the name, the value and the underlying property metadata (such as attributes), so you’ve got a great deal of flexibility to sort and group items as your specific application requires.

For example, suppose you’re using the WPF Property Grid to display and edit a set of dates — maybe milestones in a project plan represented as a Dictionary. It might be more natural to sort and group these by date — that is, by the property value — rather than by name. No problem:

public partial class Window1 : Window
{
  private void SortAndGroupGridByDate()
  {
    ICollectionView view = propertyGrid1.BindingView.DefaultView;
 
    PropertyGroupDescription grouper = new PropertyGroupDescription("Node.Value", new DateToMonthConverter());
    view.GroupDescriptions.Add(grouper);
 
    SortDescription sorter = new SortDescription("Node.Value", ListSortDirection.Ascending);
    view.SortDescriptions.Add(sorter);
  }
}
 
public class DateToMonthConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    if (value is DateTime)
    {
      return ((DateTime)value).ToString("MMMM yyyy");
    }
    else
    {
      return "Non-Dates";
    }
  }
 
  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}

This gives a result like this:

Screenshot of property grid entries sorted and grouped by value

In summary, although the WPF Property Grid, unlike the Windows Forms equivalent, doesn’t have a sorting and grouping API per se, its use of the WPF collection view idiom gives you a great deal more freedom to present your data organised in a way which is appropriate to your application and your users’ needs.

3 Responses to “Sorting and grouping in the WPF Property Grid”

  1. this is helpful, Ivan – how do I hook the firstletterconverter and groupfirstletter methods in the xaml? I have the code, but it doesn’t fire…

  2. Oops, sorry, that wasn’t very clear. You would call the GroupByFirstLetter (or equivalent) method from the code-behind, typically in the window constructor. E.g.

    public Window1()
    {
    InitializeComponent();

    propertyGrid1.SelectedObject = new Preferences();
    GroupByFirstLetter(propertyGrid1);
    }

    Apologies for the confusion.

  3. [...] in January, I wrote about sorting and grouping in the WPF Property Grid. I described how to sort entries using [...]

Leave a Reply

Data Products Visual Controls Community Store
LightSpeed ORM
NHibernate Designer
SimpleDB Tools
SharePoint Tools
WPF Elements
WPF Diagrams
Silverlight Elements
Forums
Blog
Register
Login
Subscribe to newsletter
Buy Now
My Account
Volume Discounts
Purchase Orders
Contact Us