WPF DataGrid CustomSort for each Column

后端 未结 10 1492
庸人自扰
庸人自扰 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:13

    I created a couple of attached properties which handle this issue. I hope this comes in handy for someone!

    First - a simple interface for your directionalised comparer. This extends IComparer but gives us one more property (SortDirection). Your implementation should use this to determine the correct ordering of elements (which would otherwise have been lost).

    public interface ICustomSorter : IComparer
    {
        ListSortDirection SortDirection { get; set; }
    }
    

    Next is the attached behavior - this does two things: 1) tells the grid to use custom sort logic (AllowCustomSort=true) and b) gives us the ability to set this logic at a per-column level.

    public class CustomSortBehaviour
    {
        public static readonly DependencyProperty CustomSorterProperty =
            DependencyProperty.RegisterAttached("CustomSorter", typeof(ICustomSorter), typeof(CustomSortBehaviour));
    
        public static ICustomSorter GetCustomSorter(DataGridColumn gridColumn)
        {
            return (ICustomSorter)gridColumn.GetValue(CustomSorterProperty);
        }
    
        public static void SetCustomSorter(DataGridColumn gridColumn, ICustomSorter value)
        {
            gridColumn.SetValue(CustomSorterProperty, value);
        }
    
        public static readonly DependencyProperty AllowCustomSortProperty =
            DependencyProperty.RegisterAttached("AllowCustomSort", typeof(bool),
            typeof(CustomSortBehaviour), new UIPropertyMetadata(false, OnAllowCustomSortChanged));
    
        public static bool GetAllowCustomSort(DataGrid grid)
        {
            return (bool)grid.GetValue(AllowCustomSortProperty);
        }
    
        public static void SetAllowCustomSort(DataGrid grid, bool value)
        {
            grid.SetValue(AllowCustomSortProperty, value);
        }
    
        private static void OnAllowCustomSortChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var existing = d as DataGrid;
            if (existing == null) return;
    
            var oldAllow = (bool)e.OldValue;
            var newAllow = (bool)e.NewValue;
    
            if (!oldAllow && newAllow)
            {
                existing.Sorting += HandleCustomSorting;
            }
            else
            {
                existing.Sorting -= HandleCustomSorting;
            }
        }
    
        private static void HandleCustomSorting(object sender, DataGridSortingEventArgs e)
        {
            var dataGrid = sender as DataGrid;
            if (dataGrid == null || !GetAllowCustomSort(dataGrid)) return;
    
            var listColView = dataGrid.ItemsSource as ListCollectionView;
            if (listColView == null)
                throw new Exception("The DataGrid's ItemsSource property must be of type, ListCollectionView");
    
            // Sanity check
            var sorter = GetCustomSorter(e.Column);
            if (sorter == null) return;
    
            // The guts.
            e.Handled = true;
    
            var direction = (e.Column.SortDirection != ListSortDirection.Ascending)
                                ? ListSortDirection.Ascending
                                : ListSortDirection.Descending;
    
            e.Column.SortDirection = sorter.SortDirection = direction;
            listColView.CustomSort = sorter;
        }
    }
    

    To use it, implement an ICustomComparer (with a parameterless constructor) and in your XAML:

    
        
        
    
    
        
            
        
    
    

提交回复
热议问题