WPF DataGrid CustomSort for each Column

后端 未结 10 1423
庸人自扰
庸人自扰 2020-12-01 01:56

I have a WPF DataGrid bound to a CollectionViewSource that encapsulates an ObservableCollection. This CollectionViewSource has two main objectives:

1) To group each

相关标签:
10条回答
  • 2020-12-01 02:23

    I did this by overriding the OnSorting event and implementing it myself.

    http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.onsorting.aspx

    Which basically meant re sorting the ListCollectionView.

    Sorry its not too in depth an answer.

    0 讨论(0)
  • 2020-12-01 02:23

    DataGrid CustomSorting

    <DataGrid attached:DataGridHelpers.UseCustomSort="True" ItemsSource="{Binding Items}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn attached:DataGridHelpers.CustomSorterType="{x:Type comparers:StrLogicalComparer}" Binding="{Binding CodeText}" Header="Code"  />
            <DataGridTextColumn Header="Number" Binding="{Binding Number}" />
        </DataGrid.Columns>
    </DataGrid>
    

    Supports nested properties

    0 讨论(0)
  • 2020-12-01 02:28

    This answer is very similar to trilson86's solution -- it was based on it -- but it accounts for SortMemberPath in a manner such that the values passed to your comparer are the actual values of the column, rather than the rows. This facilitates far greater re-use on your sorters. Furthermore, it eliminates the need for a custom sort interface altogether.

    DataGridSortBehavior.cs

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Reflection;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    
    namespace YourNamespace
    {
        public class DataGridSortBehavior 
        {
            public static IComparer GetSorter(DataGridColumn column)
            {
                return (IComparer)column.GetValue(SorterProperty);
            }
    
            public static void SetSorter(DataGridColumn column, IComparer value)
            {
                column.SetValue(SorterProperty, value);
            }
    
            public static bool GetAllowCustomSort(DataGrid grid)
            {
                return (bool)grid.GetValue(AllowCustomSortProperty);
            }
    
            public static void SetAllowCustomSort(DataGrid grid, bool value)
            {
                grid.SetValue(AllowCustomSortProperty, value);
            }
    
            public static readonly DependencyProperty SorterProperty = DependencyProperty.RegisterAttached("Sorter", typeof(IComparer), 
                typeof(DataGridSortBehavior));
            public static readonly DependencyProperty AllowCustomSortProperty = DependencyProperty.RegisterAttached("AllowCustomSort", typeof(bool), 
                typeof(DataGridSortBehavior), new UIPropertyMetadata(false, OnAllowCustomSortChanged));
    
            private static void OnAllowCustomSortChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
            {
                var grid = (DataGrid)obj;
    
                bool oldAllow = (bool)e.OldValue;
                bool newAllow = (bool)e.NewValue;
    
                if (!oldAllow && newAllow)
                {
                    grid.Sorting += HandleCustomSorting;
                }
                else
                {
                    grid.Sorting -= HandleCustomSorting;
                }
            }
    
            public static bool ApplySort(DataGrid grid, DataGridColumn column)
            {
                IComparer sorter = GetSorter(column);
                if (sorter == null)
                {
                    return false;
                }
    
                var listCollectionView = CollectionViewSource.GetDefaultView(grid.ItemsSource) as ListCollectionView;
                if (listCollectionView == null)
                {
                    throw new Exception("The ICollectionView associated with the DataGrid must be of type, ListCollectionView");
                }
    
                listCollectionView.CustomSort = new DataGridSortComparer(sorter, column.SortDirection ?? ListSortDirection.Ascending, column.SortMemberPath);
                return true;
            }
    
            private static void HandleCustomSorting(object sender, DataGridSortingEventArgs e)
            {
                IComparer sorter = GetSorter(e.Column);
                if (sorter == null)
                {
                    return;
                }
    
                var grid = (DataGrid)sender;
                e.Column.SortDirection = e.Column.SortDirection == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending;
                if (ApplySort(grid, e.Column))
                {
                    e.Handled = true;
                }
            }
    
            private class DataGridSortComparer : IComparer
            {
                private IComparer comparer;
                private ListSortDirection sortDirection;
                private string propertyName;
                private PropertyInfo property;
    
                public DataGridSortComparer(IComparer comparer, ListSortDirection sortDirection, string propertyName)
                {
                    this.comparer = comparer;
                    this.sortDirection = sortDirection;
                    this.propertyName = propertyName;
                }
    
                public int Compare(object x, object y)
                {
                    PropertyInfo property = this.property ?? (this.property = x.GetType().GetProperty(propertyName));
                    object value1 = property.GetValue(x);
                    object value2 = property.GetValue(y);
    
                    int result = comparer.Compare(value1, value2);
                    if (sortDirection == ListSortDirection.Descending)
                    {
                        result = -result;
                    }
                    return result;
                }
            }
        }
    }
    

    Your Xaml

    This should look similar to trilson86's solution as well:

    <UserControl.Resources>
        <converters:MyComparer x:Key="MyComparer"/>
    </UserControl.Resources>
    <DataGrid behaviours:DataGridSortBehavior.AllowCustomSort="True" ItemsSource="{Binding MyListCollectionView}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Test" Binding="{Binding MyValue}" behaviours:DataGridSortBehavior.Sorter="{StaticResource MyComparer}" />
        </DataGrid.Columns>
    </DataGrid>
    
    0 讨论(0)
  • 2020-12-01 02:28

    you can use this in case that you adding the columns programatically .

    dg_show.Items.SortDescriptions.Add(new System.ComponentModel.SortDescription("val1", System.ComponentModel.ListSortDirection.Descending));
    

    "val1" here is the binding path for the column we added , and you can also using another line as a second sort . like this one .

            dg_show.Items.SortDescriptions.Add(new System.ComponentModel.SortDescription("val2", System.ComponentModel.ListSortDirection.Ascending));
    
    0 讨论(0)
提交回复
热议问题