ChangeTracking icon indicating copy to clipboard operation
ChangeTracking copied to clipboard

Unable to sort trackable collection in DataGrid.

Open ericdc66 opened this issue 6 years ago • 11 comments

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.

ericdc66 avatar Sep 11 '18 13:09 ericdc66

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);
     }
}

toumir avatar Sep 11 '18 19:09 toumir

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.

ericdc66 avatar Sep 11 '18 21:09 ericdc66

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());

joelweiss avatar Sep 12 '18 23:09 joelweiss

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?

ericdc66 avatar Sep 13 '18 20:09 ericdc66

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.

joelweiss avatar Sep 14 '18 22:09 joelweiss

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 avatar Sep 16 '18 08:09 toumir

@toumir

ObservableCollection<T> can not be supported as it is a class, only interfaces can be swapped out for a trackable collection.

joelweiss avatar Sep 17 '18 21:09 joelweiss

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.

ericdc66 avatar Sep 23 '18 23:09 ericdc66

Hi, would also like to see this, whats the status on this? thx

xtds avatar Nov 08 '18 11:11 xtds

I will work on it as soon as I have a chance

joelweiss avatar Nov 09 '18 03:11 joelweiss

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.

xtds avatar Nov 28 '18 10:11 xtds