Hi,
We have an ObservableCollection of ViewModels bound to a XamDataGrid. This viewModel holds a number of string based values that are exposed as public properties complete with PropertyChanged syntax. These string based values are set from a numeric property on the same viewModel via a ValueConverter when the ViewModel is created. We do this in order to improve performance (as recommended by Infragistics), otherwise scrolling between rows makes the grid unusable as the ValueConverters are continuously called. By setting them when the viewModel is created, we 'bloat' our viewModel with what is a numeric and textual representation of the same value in order to ensure that the ValueConverters will not be needed at the XamDataContext field level.
This presents a problem to us. In this example, I have a viewModel with a 'Quantity' property and a 'QuantityText' property. We use the QuantityText property as a column on the grid. When we sort the QuantityText we do not want this:
We want this:
To get this, I simply want the QuantityText column to sort by the Quantity property on the rows DataContext instead. That ought to be simple.
So far though, I have had no luck in finding a reasonable answer having trawled through endless number of forum posts.
I cannot use an IComparer instance because I only get the QuantityText values passed into X and Y. Unfortunately, The XamDataGrid doesn't work like the XamGrid where we are given the entire DataContext in X and Y, meaning we could then sort appropriately on the relevant viewModel properties.
I have also tried an answer where a GroupEvaluator is used to provide a custom IComparer, but this is no good either because I don't have any grouping on the grid.
I am somewhat loathe to have to write code in the code-behind or in a behaviour in order to get at the GridSorting event and manage it myself - I don't believe it's reasonable that customers would be required to go to such lengths to complete a relatively simple operation on a well-established grid.
Can you please advise what I can do here?
Thanks,Russell
Hi Russell,
Can you point me towards the support case or forum thread where we recommended extra properties for performance reasons? I can definitely see how converters can potentially slow down scrolling speed since they fire for new records coming into view but they shouldn't be making the grid unusable as long as the logic inside the converter is not heavy. It would be nice to see why we recommended this as maybe there is a better way to do this.
You are right about the IComparer though. It only giving you the value that the field is attached to. If you want to work with the whole row object in order to obtain a different property to work with you will need to give your QuantityText Field an alternate binding. The Field class has a BindingType property which you can set to "UseAlternateBinding". It also as an AlternateBinding property which you can set to a Binding object. This is where you will tell the Field that it should bind to the whole row object.
<igDP:Field Name="QuantityText" BindingType="UseAlternateBinding" AlternateBinding="{Binding}"> <igDP:Field.Settings> <igDP:FieldSettings SortComparer="{StaticResource mySortComparer}"/> Unfortunately the issue with this approach is that you now change what the displayed cell value will be. Since we changed the binding to point at the whole row object it's going to display the row object ToString(). To get around that you are going to need to provide a display template for the field which means using a TemplateField. You can still using the alternate binding properties but now you will have to provide a template that will display which property you actually want to show. If you want to allow editing of this field then you will need to provide an EditTemplate as well.
<igDP:TemplateField Name="QuantityText" BindingType="UseAlternateBinding" AlternateBinding="{Binding}"> <igDP:TemplateField.Settings> <igDP:FieldSettings SortComparer="{StaticResource mySortComparer}"/> </igDP:TemplateField.Settings> <igDP:TemplateField.DisplayTemplate> <DataTemplate> <TextBlock Text="{Binding QuantityText}"/> </DataTemplate> </igDP:TemplateField.DisplayTemplate> I think we should re-examine why you can't use a value converter in order to convert your numeric value into the desired format. I just can't see that type of conversion being something that would impact performance to the point that scrolling is unusable. Please let me know if there was a private case or a forum thread where we helped you with this in the past.
Hi Rob,
Thanks for your detailed response, that's great - very much appreciated.
I've had a look for the suggestion of 'extra viewModel properties', but I can't seem to find anything on any forum or whitepaper. I think we initially came up with the idea ourselves, though I remain convinced that we found some additional resource suggesting that others had followed a similar approach. The majority of our ValueConverters are lightweight, but there are times when we represent a single value across a multitude of financial instruments (traded in different ways) that need some clever logic to display correctly, and that logic is a little cumbersome. Please bear in mind that our grid is somewhat more complex than those provided in your samples - in addition to having thousands more rows, specific cell styles for various rules, and a large number of columns, we are also using a recycle approach to virtualisation (it's too lengthy and memory consuming to load the entire grid contents) and a ScrollingMode set to Immediate (users generally dislike IsScrollTipField).
I ought to mention that we have also discussed this with our Infragistics contact in person (on one of his site visits), and he agreed that our approach would aid in performance whilst scrolling.
Regarding the filtering itself...thanks for providing a workaround to the issue that I'm facing. I think the approach to using an AlternateBinding, a SortComparer and a corresponding DataTemplate within a Template column is a reasonable enough solution. I'd rather add a little more XAML than have to write a generic behaviour that swaps out one column's sort for another.
Many Thanks,Russell