ChangeTracking
ChangeTracking copied to clipboard
Unable to sort trackable collection in DataGrid.
Normally, a WPF DataGrid will sort a collection by clicking on column headers. If I apply AsTrackable() to the collection, then sorting no longer works. The sort indicators on the column header still shows the direction of the sort, but the rows do not change to show the sort order.
Here's an example:
MainWindow.xaml:
<Window x:Class="ChangeTrackingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<DataGrid CanUserAddRows="False" CanUserSortColumns="True" AutoGenerateColumns="False" ItemsSource="{Binding TestData}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" CanUserSort="True" Header="Name"/>
<DataGridTextColumn Binding="{Binding Desc}" CanUserSort="True" Header="Description"/>
</DataGrid.Columns>
</DataGrid>
</Window>
MainWindow.xaml.cs:
using System.Collections.Generic;
using System.Windows;
using ChangeTracking;
namespace ChangeTrackingTest
{
public class Data
{
public virtual string Name { get; set; }
public virtual string Desc { get; set; }
public Data() { }
public Data(string name, string desc)
{
Name = name;
Desc = desc;
}
}
public class ViewModel
{
public IList<Data> TestData { get; set; }
public ViewModel(IList<Data> data)
{
TestData = data;
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
//var data = GetData(); // This sorts but isn't Trackable
var data = GetData().AsTrackable(); // This is Trackable but won't sort
var viewModel = new ViewModel(data);
DataContext = viewModel;
InitializeComponent();
}
private static IList<Data> GetData()
{
return new List<Data>()
{
new Data("Train", "My train"),
new Data("Car", "My car"),
new Data("Plane", "My plane")
};
}
}
}
Switch the comments on the var data
statements in the MainWindow constructor to see that it is just AsTrackable() that breaks sorting.
Does this do the trick ? change the TestData to OC
public class ViewModel
{
public ObservableCollection<Data> TestData { get; set; }
public ViewModel(IList<Data> data)
{
TestData = new ObservableCollection<Data>(data);
}
}
The DataGrid will sort using an OC. However, since the items are copied from the Trackable list to an internal collection of the OC, the OC list is not Trackable. The original (Trackable) list still detects items changed from editing in the grid because the references are shared between the two lists. The original list does not detect items added or removed from the grid, as these only affect the OC.
ChangeTracking
internaly uses BindingList<T>
and as you can see BindingList<T>
does not support sorting.
this fails to sort as well
//var data = GetData(); // This sorts but isn't Trackable
//var data = GetData().AsTrackable(); // This is Trackable but won't sort
var data = new BindingList<Data>(GetData());
I guess that explains why it doesn't work. Can the internal BindingList<T>
be changed to something that would work? What are the advantages for using BindingList<T>
versus the consequences/issues around changing it to something like ObservableCollection<T>
or perhaps something configurable to the user?
Short version is ObservableCollection<T>
only provides change notification on the list it self, BindingList<T>
has a lot more of the stuff needed to make ChangeTracking
work.
That being said I might have a fix for this, let's keep this issue open.
Great job Nice to add this feature, it will bring a lot :) especially UI notification : Please Support ObservableCollection Properties
public class Order
{
public virtual int Id { get; set; }
//...
public virtual ObservableCollection<OrderDetail> Details { get; set; }
//...
}
Thanks
@toumir
ObservableCollection<T>
can not be supported as it is a class, only interfaces can be swapped out for a trackable collection.
While BindingList<T>
doesn't implement sorting, it does provide the methods so that a derived class can do so. I modified ChangeTrackingBindingList<T>
to provide sorting as shown in https://www.codeproject.com/articles/31418/implementing-a-sortable-bindinglist-very-very-quic. I had to change the sorting implementation a little to work with the ChangeTrackingBindingList<T>
implementation, but it can be done.
Incidentally, I've also added an implementation of INotifyDataErrorInfo
to provide for validation of change tracked items. The validation is implemented to use attributes as defined in System.ComponentModel.DataAnnotations
and through a List<ValidationResult> Validate(string propertyName)
method on the class of objects being change tracked.
Hi, would also like to see this, whats the status on this? thx
I will work on it as soon as I have a chance
Hi again, Without going much into detail I checked the article, forked your code, and tried it myself. It seems to be a sufficient solution thus far for me.