External Sorting / Grouping / Filtering / Aggregation with the WPF XamDataGrid

Damyan Petev / Monday, May 7, 2012

Sorting, filtering, grouping and summaries, thus far, have always been performed been performed internally by the Data Presenter – it was designed after all to be the backbone of data-driven controls and it provides a whole armada of automatic functionality out of the box. And by offering that functionality it is nicely integrated with the presenter’s model and the UI as well. All that speaks pretty strong in favour of the presenter, but then again we’ve had plenty of requests like…

  • “How do you stop the Grid from performing its own sorting?”
  • “How do you achieve full virtualization?” (as in adding data virtualization to the already available range of UI virtualization)
  • “How to perform <insert operation here> with custom logic/on a server side?”
  • etc.

And those are just a few you can see in forums and then there’re feature requests too. The point is, even with all those things you have provided, those requests are not without reason. Actually there are some benefits to be drawn from performing such operations externally and now you can do that without any workarounds with the introduction of a new CTP feature that allows performing operations outside the grid.

Differences and profits

Performance

One very important thing to note – when the Data Presenter internally handles any of those actions, it needs to allocate memory for as many DataRecord objects as the items to be processed.Mind you, those record objects as usually created in a lazy manner. That simply put means that it takes some memory and processor time to do that before the operation itself begins. Therefore, if you choose to take the operation execution outside, you could gain some performance improvement. And with extremely large data that can suddenly become quite meaningful. While the demo project I’ll use for this blog is somewhat shy ( rocking just a bit over 800 records of Orders from Northwind), measurements even with quite low numbers still shows some slight boost on the initial sort for that reason. Pumping the data 5 times to 4150 items yielded such results on my slightly struggling test machine when sorted by ship address:

A comparison showing that using ListCollectionView can improve performance even with just 4000+ records.

Keep in mind the benefits of this would be tightly coupled with the size and type of your data. The reason why the ListCollectionView can add performance boost is that it implements IList, that due to the interface providing indexer, performs much better with large sets of data than IEnumerable and ICollection. One other thing is that IEnumerable doesn’t provide a Count property neither does it provide mechanisms to perform sorting and other operations. That combined with the reduced memory and time to create objects as described above makes for a nice performance enhancement. Also you could perform the sorting manually which should once again prove helpful with large data.

Now imagine much bigger data sets with more fields per records(would result in bigger DataRecords created), like 100 000 records. Such type of samples you can find in our samples browser( you can get you hands on it by visiting the download page for NetAdvantage for WPF) implementing both ListColletionView and manual IEnumerable operations, both of which should prove faster that the default.

Functionality

As mentioned, you can perform sorting / filtering / grouping / aggregation manually and this gives you a great opportunity to also implement you own logic! Take the screenshot above – addresses beginning with numbers means that string sorting will not really do a good job sorting those and you can fix that by implementing it yourself. And the best part of having total control over the process means you can go on and use remote server to do that and just consume the result!

Also there’s the fact you can enjoy other benefits with the ListCollectionView – changes performed on the collection (such as modifying the  ‘SortDescriptions’ or ones coming from other bound elements) will be picked up by the presenter and reflected in its UI and vice versa. That is exactly what would happen when the grid uses it and judging by the plural form you can guess multiple sorted columns(except unbound) would be supported.

How?

Lets have a look at some snippets that can make this happen – now first and foremost you will need the latest release(12.1), so make sure that’s covered. For the ListCollectionView implementation(assuming you are already familiar with how to add a xamDataGrid to your page and set up data) you can rely entirely on the built-in functions and simply instruct the grid to use them like so:

  1. <igDP:XamDataGrid x:Name="xamDataGrid">
  2.     <igDP:XamDataGrid.FieldLayoutSettings>
  3.         <igDP:FieldLayoutSettings
  4.             AutoGenerateFields="True"
  5.             SortEvaluationMode="UseCollectionView"
  6.             FilterEvaluationMode="UseCollectionView"
  7.             GroupByEvaluationMode="UseCollectionView"
  8.             SummaryEvaluationMode="UseLinq" />
  9.     </igDP:XamDataGrid.FieldLayoutSettings>
  10. </igDP:XamDataGrid>

The relevant affected fields above are the SortEvaluationMode, FilterEvaluationMode and GroupEvalulationMode and are set to UseCollectionView. They dictate the way operations are to be handled and also have default setting (using the data presenter) and manual one we’ll look into below.

The Summary similarly also has default and manual setting and a LINQ one to use with ListCollectionView.

Setting any of the four main features to ‘Manual” means the data presenter will not attempt to process user's actions and will leave that to you, which is ideal if you plan on virtualizing your data. It is also what we would do in the second demo:

  1. <igDP:XamDataGrid x:Name="xamDataGrid">
  2.     <igDP:XamDataGrid.FieldLayoutSettings>
  3.         <igDP:FieldLayoutSettings
  4.             AutoGenerateFields="True"
  5.             SortEvaluationMode="Manual"/>
  6.     </igDP:XamDataGrid.FieldLayoutSettings>
  7. </igDP:XamDataGrid>

Now for the actual work to happen you we can use the respective operations’ events to get information about the user interaction and execute our custom logic or get data from the server:

 

  1. void xamDataGrid_Sorting(object sender, Infragistics.Windows.DataPresenter.Events.SortingEventArgs e)
  2. {
  3.     // Get sorted data from the server using the event's arguments to get information for the column key and the order.
  4.     sortedInfo = e.Field.Name;
  5.     if (e.SortDescription.Direction == System.ComponentModel.ListSortDirection.Descending)
  6.     {
  7.          sortedInfo += " desc";
  8.     }
  9.     data = new ObservableCollection<Order>(client.SortData(sortedInfo, page + 1));
  10.     this.xamDataGrid.DataSource = data;
  11. }

 

There’s plenty of code I’ll be skipping you can find in the demo, but to clarify here – the client is for the service that reads Northwind from local SQL (the service acts as the server side in this case). The service is using a Dynamic LINQ library you can download directly with NuGet or from MSDN. You do NOT have to download it to run the demo, it’s already there. The library allows to easily sort by name of the field, which is very comfy considering we have to send it to the server, and also combines the order with the name (additional “ desc” means Descending) which also reduces the amount of parameters to send.

This is just one way to do it and can probably be improved upon, but the point is those events will tell you when and also provide the field name to sort by and the orientation. You can approach all other operations in very much the same way - RecordFilterDropDownPopulating or RecordFilterDropDownOpening events to add custom filter operands and so on. Again I encourage you to download NetAdvantage for WPF, try the samples Under performance to see implementations for all operations and give the demo below a try.

Conclusion

This feature extends the already rich functionality of the powerful XamDataGrid control. It opens new possibilities to fine-tune the performance of such essential operations like sorting, filtering, grouping and aggregation. It allows to reduce memory and processor time by performing them externally using a very suited for the job ListCollectionView or manually with your own logic, which can be used to improve on the functionality or perform those operations on a remote server. Even as CTP the feature keeps limitations to a minimum and strives to provide you with the control you need and maintain the very same user experience.

You can download the demo project. Visit http://www.infragistics.com to get the latest bits, follow us on Twitter @Infragistics and don’t forget about our on-going competition on Facebook. Build the best HTML/jQuery app and perhaps be rewarded with an iPad3!