Search code examples
c#wpfsortingdatagrid

Two datagrids with same sorting wpf


I have two datagrids which is bound to two datatables as itemsource Datagrids. I want to be able to sort both datagrid columns when clicked on one of the headers. When the property: "CanUserSortColumns="True"" is set to true, the datagrids will not sort together. What I want is when clicked on column header, the row from either datagrid 1 or datagrid 2 will follow the sorting, so the row matches the sorting.

I have looked into this abit and saw that dataviewer can be used to sorting(since it is bound to datatable), also saw that a CollectionView can be used, but I cant see any examples of doing this with two datagrids, only with one.

Sorting only one datagrid(What I have): Image of what I have

Sorting both datagrid by clicking header(What I need): Image of what i need

Is there a why to do this? Both datagrids have the same number of rows.


Solution

  • Here's an attached property that should help you, I just coded it kinda quick and dirty so I think you can make sure I didn't forget anything before using (and edit the answer if I did). You can use it this way in XAML :

    <DataGrid local:DatagridBehaviour.SyncSortingWith="{Binding ElementName=otherDataGrid}"/>
    <DataGrid Name="otherDataGrid"/>
    

    Attached Property :

    public static class DatagridBehaviour
    {
        public static DataGrid GetSyncSortingWith(DependencyObject obj)
        {
            return (DataGrid)obj.GetValue(SyncSortingWithProperty);
        }
    
        public static void SetSyncSortingWith(DependencyObject obj, DataGrid value)
        {
            obj.SetValue(SyncSortingWithProperty, value);
        }
    
        public static readonly DependencyProperty SyncSortingWithProperty = DependencyProperty.RegisterAttached("SyncSortingWith", typeof(DataGrid), typeof(DatagridBehaviour), new PropertyMetadata(OnSyncSortingWithChanged));
    
        private static void OnSyncSortingWithChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is DataGrid source)
            {
                source.Sorting -= DataGridSorting;
                if (e.NewValue is DataGrid other)
                {
                    other.Sorting += DataGridSorting;
                    source.Sorting += DataGridSorting;
                }
    
                if (e.OldValue is DataGrid previous)
                {
                    previous.Sorting -= DataGridSorting;
                }
            }
        }
    
        private static void DataGridSorting(object sender, DataGridSortingEventArgs e)
        {
            if (sender is DataGrid dataGrid)
            {
                DataGridColumn column = dataGrid.Columns[0];
                dataGrid.Items.SortDescriptions.Clear();
                dataGrid.Items.SortDescriptions.Add(new SortDescription(column.SortMemberPath, column.SortDirection == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending));
    
                // May not be needed
                dataGrid.Items.Refresh();
            }
        }
    }
    

    The only thing you'll need for it to work is having the same bindings path on the columns of both datagrids.