WPF DataGrid CustomSort dla każdej kolumny

Mam DataGrid WPF związany z CollectionViewSource, który zawiera Obserwowalną kolekcję. Ta kolekcja Viewsource ma dwa główne cele:

1) aby pogrupować każdy element według określonej właściwości T. używam ValueConverter w opisie GroupDescription, aby uzyskać pożądane zachowanie grupowania.

2) sortowanie siatki według a) przede wszystkim nazwy grupy (jak zdefiniowano powyżej) i B) poszczególnych elementów grupy. Osiągam to poprzez dołączenie niestandardowego Icomparera do CollectionViewSource' s 'CustomSort' property.

To działa świetnie w większości przypadków, Jednak gdy tylko klikniesz nagłówek kolumny, logika sortowania zostanie nadpisana. Nie chcę wyłączać sortowania, jednak zastanawiałem się, czy można przypisać Niestandardowy porządek sortowania dla konkretnej kolumny?

Aby wszystko było jaśniejsze, Załóżmy, że użytkownik kliknie "ColumnA" - w tej chwili logika sortowania zawarta w moim CustomSorter jest nadpisana, a DataGrid jest teraz sortowany według tego własność. Zamiast sortować według wybranej właściwości, chciałbym zamiast tego odwrócić logikę CustomSorter.

Author: trilson86, 2013-08-08

10 answers

Stworzyłem kilka dołączonych właściwości, które rozwiązują ten problem. Mam nadzieję, że to się komuś przyda!

Po pierwsze-prosty interfejs dla Twojego komparatora kierunkowego. To rozszerza IComparer, ale daje nam jeszcze jedną właściwość (SortDirection). Twoja implementacja powinna użyć tego do określenia poprawnej kolejności elementów (które w przeciwnym razie zostałyby utracone).

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

Następnie jest dołączone zachowanie - robi to dwie rzeczy: 1) mówi siatce, aby używała niestandardowej logiki sortowania (AllowCustomSort = true) I b) daje nam możliwość ustawienia tej logiki na poziomie każdej kolumny.

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

Aby go użyć, zaimplementuj ICustomComparer (z konstruktorem bez parametru) i w swoim XAML:

<UserControl.Resources>
    <converters:MyComparer x:Key="MyComparer"/>
    <!-- add more if you need them -->
</UserControl.Resources>
<DataGrid behaviours:CustomSortBehaviour.AllowCustomSort="True" ItemsSource="{Binding MyListCollectionView}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Test" Binding="{Binding MyValue}" behaviours:CustomSortBehaviour.CustomSorter="{StaticResource MyComparer}" />
    </DataGrid.Columns>
</DataGrid>
 30
Author: trilson86,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-04 08:27:17

Odpowiedź udzielona przez trilson86 jest doskonała. Jednak trzeci parametr w dwóch deklaracjach DependencyProperty jest nieprawidłowy. Zamiast DataGrid i DataGridColumn powinny być CustomSortBehaviour, jako takie:

public static readonly DependencyProperty AllowCustomSortProperty =
        DependencyProperty.RegisterAttached("AllowCustomSort", 
        typeof(bool),
        typeof(CustomSortBehaviour), // <- Here
        new UIPropertyMetadata(false, OnAllowCustomSortChanged));

    public static readonly DependencyProperty CustomSorterProperty =
        DependencyProperty.RegisterAttached("CustomSorter", 
        typeof(ICustomSorter), 
        typeof(CustomSortBehaviour));  // <- Here

Otrzymywałem ostrzeżenie, że właściwość AllowCustomSort została już zarejestrowana. Trochę badań doprowadziło mnie do odpowiedzi Tutaj .

W każdym razie, to doskonała odpowiedź, więc dziękuję.
 5
Author: pennyrave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:09

Jest jeden sposób:

using System;
using System.Collections;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

public static class DataGridSort
{
    public static readonly DependencyProperty ComparerProperty = DependencyProperty.RegisterAttached(
        "Comparer",
        typeof(IComparer),
        typeof(DataGridSort),
        new PropertyMetadata(
            default(IComparer),
            OnComparerChanged));

    private static readonly DependencyProperty ColumnComparerProperty = DependencyProperty.RegisterAttached(
        "ColumnComparer",
        typeof(ColumnComparer),
        typeof(DataGridSort),
        new PropertyMetadata(default(ColumnComparer)));

    private static readonly DependencyProperty PreviousComparerProperty = DependencyProperty.RegisterAttached(
        "PreviousComparer",
        typeof(IComparer),
        typeof(DataGridSort),
        new PropertyMetadata(default(IComparer)));

    public static readonly DependencyProperty UseCustomSortProperty = DependencyProperty.RegisterAttached(
        "UseCustomSort",
        typeof(bool),
        typeof(DataGridSort),
        new PropertyMetadata(default(bool), OnUseCustomSortChanged));

    public static void SetComparer(DataGridColumn element, IComparer value)
    {
        element.SetValue(ComparerProperty, value);
    }

    public static IComparer GetComparer(DataGridColumn element)
    {
        return (IComparer)element.GetValue(ComparerProperty);
    }

    public static void SetUseCustomSort(DependencyObject element, bool value)
    {
        element.SetValue(UseCustomSortProperty, value);
    }

    public static bool GetUseCustomSort(DependencyObject element)
    {
        return (bool)element.GetValue(UseCustomSortProperty);
    }

    private static void OnComparerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var column = (DataGridColumn)d;
        var columnComparer = new ColumnComparer((IComparer)e.NewValue, column);
        column.SetValue(ColumnComparerProperty, columnComparer);
    }

    private static void OnUseCustomSortChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var dataGrid = (DataGrid)d;
        if ((bool)e.NewValue)
        {
            WeakEventManager<DataGrid, DataGridSortingEventArgs>.AddHandler(dataGrid, nameof(dataGrid.Sorting), OnDataGridSorting);
        }
        else
        {
            WeakEventManager<DataGrid, DataGridSortingEventArgs>.RemoveHandler(dataGrid, nameof(dataGrid.Sorting), OnDataGridSorting);
        }
    }

    private static void OnDataGridSorting(object sender, DataGridSortingEventArgs e)
    {
        var column = e.Column;
        var columnComparer = (ColumnComparer)column.GetValue(ColumnComparerProperty);
        var dataGrid = (DataGrid)sender;
        var view = CollectionViewSource.GetDefaultView(dataGrid.ItemsSource) as ListCollectionView;
        if (view == null)
        {
            return;
        }
        if (columnComparer == null)
        {
            view.CustomSort = (IComparer)dataGrid.GetValue(PreviousComparerProperty);
        }
        else
        {
            if (!(view.CustomSort is ColumnComparer))
            {
                dataGrid.SetValue(PreviousComparerProperty, view.CustomSort);
            }

            switch (column.SortDirection)
            {
                case ListSortDirection.Ascending:
                    column.SortDirection = ListSortDirection.Descending;
                    view.CustomSort = columnComparer.Descending;
                    break;
                case null:
                case ListSortDirection.Descending:
                    column.SortDirection = ListSortDirection.Ascending;
                    view.CustomSort = columnComparer.Ascending;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            e.Handled = true;
        }
    }

    private class ColumnComparer : IComparer
    {
        private readonly IComparer valueComparer;
        private readonly DataGridColumn column;
        private readonly InvertedComparer inverted;

        public ColumnComparer(IComparer valueComparer, DataGridColumn column)
        {
            this.valueComparer = valueComparer;
            this.column = column;
            inverted = new InvertedComparer(this);
        }

        public IComparer Ascending => this;

        public IComparer Descending => inverted;

        int IComparer.Compare(object x, object y)
        {
            if (x == y)
            {
                return 0;
            }

            if (x == null)
            {
                return -1;
            }

            if (y == null)
            {
                return 1;
            }

            // this can perhaps be a bit slow
            // Not adding caching yet.
            var xProp = x.GetType().GetProperty(column.SortMemberPath);
            var xValue = xProp.GetValue(x);
            var yProp = x.GetType().GetProperty(column.SortMemberPath);
            var yValue = yProp.GetValue(y);
            return valueComparer.Compare(xValue, yValue);
        }

        private class InvertedComparer : IComparer
        {
            private readonly IComparer comparer;

            public InvertedComparer(IComparer comparer)
            {
                this.comparer = comparer;
            }

            public int Compare(object x, object y)
            {
                return comparer.Compare(y, x);
            }
        }
    }
}

Użycie:

<DataGrid AutoGenerateColumns="False"
            ItemsSource="{Binding DataItems}"
            local:DataGridSort.UseCustomSort="True">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Key}"
                            Header="Key"
                            local:DataGridSort.Comparer="{x:Static local:StringLengthComparer.Default}" />
        <DataGridTextColumn Binding="{Binding Value}" Header="Value" />
    </DataGrid.Columns>
</DataGrid>
 5
Author: Johan Larsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-15 20:59:16

Zrobiłem to przez nadpisanie zdarzenia OnSorting i wdrożenie go osobiście.

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

Co w zasadzie oznaczało ponowne sortowanie ListCollectionView.

Sorry its not too dogłębnie odpowiedź.

 2
Author: Mark Jones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-08 10:22:30

DataGrid Customs

<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>

Obsługuje zagnieżdżone właściwości

 2
Author: lezhkin11,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-15 20:58:11

Zmieniłem odpowiedź @trilson86 tak, że potrzebujesz tylko jednej niestandardowej klasy sorter dla całego DataGrid.

Najpierw interfejs:

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

    string SortMemberPath { get; set; }
}

Następnie Klasa Bevaviour, która definiuje Customsorterperty w taki sposób, że można jej używać bezpośrednio na DataGrid, a nie na DateGridRow. W HandleCustomSorting () właściwość SortMemberPath CustomSorter jest wypełniona rzeczywistą wartością z klikniętej kolumny, możesz użyć tej wartości w CustomSorter do sortowania według żądana kolumna.

public class CustomSortBehaviour
{
    #region Fields and Constants

    public static readonly DependencyProperty CustomSorterProperty =
        DependencyProperty.RegisterAttached("CustomSorter", typeof (ICustomSorter), typeof (CustomSortBehaviour));

    public static readonly DependencyProperty AllowCustomSortProperty =
        DependencyProperty.RegisterAttached("AllowCustomSort",
            typeof (bool),
            typeof (CustomSortBehaviour),
            new UIPropertyMetadata(false, OnAllowCustomSortChanged));



    #endregion

    #region public Methods

    public static bool GetAllowCustomSort(DataGrid grid)
    {
        return (bool) grid.GetValue(AllowCustomSortProperty);
    }


    public static ICustomSorter GetCustomSorter(DataGrid grid)
    {
        return (ICustomSorter)grid.GetValue(CustomSorterProperty);
    }

    public static void SetAllowCustomSort(DataGrid grid, bool value)
    {
        grid.SetValue(AllowCustomSortProperty, value);
    }


    public static void SetCustomSorter(DataGrid grid, ICustomSorter value)
    {
        grid.SetValue(CustomSorterProperty, value);
    }

    #endregion

    #region nonpublic Methods

    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(dataGrid);
        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;
        sorter.SortMemberPath = e.Column.SortMemberPath;

        listColView.CustomSort = sorter;
    }

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

    #endregion
}

Możesz go użyć w XAML tak:

<Window x:Class="..."
        xmlns:sorter="clr-namespace:...Sorting"
        ...
        >

    <Window.Resources>
        <sorter:CustomSorter x:Key="MySorter"/>
    </Window.Resources>

    <Grid>

        <DataGrid ItemsSource="{Binding ...}"
                  sorter:CustomSortBehaviour.AllowCustomSort="True"
                  sorter:CustomSortBehaviour.CustomSorter="{StaticResource MySorter}" >


            <DataGrid.Columns>
                <DataGridTextColumn Header="Column 1" Binding="{Binding Column1}"/>
                <DataGridTextColumn Header="Column 2" Binding="{Binding Column2}"/>
                <DataGridTextColumn Header="Column 3" Binding="{Binding Column3}"/>
            </DataGrid.Columns>

        </DataGrid>

    </Grid>
</Window>
 1
Author: Jens Brand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-22 13:56:47

Ta odpowiedź jest bardzo podobna do rozwiązania trilson86 - było na niej oparte - ale odpowiada SortMemberPath w taki sposób, że wartości przekazywane do porównującego są rzeczywistymi wartościami kolumny, a nie wierszy. Ułatwia to znacznie większe ponowne użycie na sortownikach. Co więcej, całkowicie eliminuje potrzebę niestandardowego interfejsu sortowania.

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

Twój Xaml

To powinno wyglądać podobnie do rozwiązania trilson86:
<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>
 1
Author: Kirk Woll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-15 00:07:43

Wiele się nauczyłem z tego pytania i tutaj podzielam sposób na to.
Ta metoda nie modyfikuje xaml, gdy jest zgodna z mvvm.
Muszę wczytać ścieżkę do DataGrid, która może być posortowana jak Eksplorator Windows.
istnieje kilka plików:

E:\Test\Item_1.txt
E:\Test\Item_04.txt
E:\Test\Item_5.txt
E:\Test\Item_10.txt

Uwaga , że posortowałem według nazwy pliku w Eksploratorze Windows.
Myślę, że okazało się, że sortowanie plików używane przez Eksploratora nie jest prostym sortowaniem ciągów.
Używa API win32 StrCmpLogicalW w shlwapi.dll
Musimy zaimplementować IComparable (Non-generic) interfejs dla posortowanych właściwości.
Za mniej kodu użyłem Prism.Mvvm.BindableBase, INotifyPropertyChanged implementation.
Kod podobny do tego:

    /// <summary>
    /// Data Model
    /// </summary>
    public class ListItemModel : BindableBase
    {

        private FilePath filePath;
        public FilePath FilePath
        {
            get { return filePath; }
            set { SetProperty(ref filePath, value); }
        }
        
        /// Other properties.
        /// ....
    }

    /// <summary>
    /// wrapper of filepath
    /// </summary>
    public class FilePath : IComparable
    {
        private string filePath;

        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
        private static extern int StrCmpLogicalW(string psz1, string psz2);

        public FilePath(string filePath)
        {
            this.filePath = filePath;
        }

        /// <summary>
        /// Implicit type conversion.
        /// </summary>
        /// <param name="x"></param>
        public static implicit operator string(FilePath x)
        {
            return x.filePath;
        }

        public static implicit operator FilePath(string x)
        {
            return new FilePath(x);
        }

        /// <summary>
        /// override for datagrid display.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return filePath;
        }

        /// <summary>
        /// Implement the interface IComparable for Custom sorting.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public int CompareTo(object obj)
        {
            if (obj is FilePath other)
                return StrCmpLogicalW(filePath, other.filePath);
            return 1;
        }
    }

Kod XAML:

        <!-- Items is ObservableCollection<ListItemModel> -->        
        <DataGrid  ItemsSource="{Binding Items}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="File" Binding="{Binding FilePath}" />
            </DataGrid.Columns>
        </DataGrid>

Podsumowując, zamknąłem oryginalne właściwości ciągu,
Można również Dodaj własne właściwości do sortowania,
wystarczy przesłać ToString do wyświetlenia i zaimplementować CompareTo do sortowania.

 1
Author: IOL0ol1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-18 10:43:47

Tu jest jakieś rozszerzenie do @ trilson86 ICustomeSorter

Które Sprawiają, że Sorter jest bardziej ogólny w użyciu

NumericComparer oparty na tym zasobie

Http://www.codeproject.com/Articles/11016/Numeric-String-Sort-in-C

public class GenericNumericComparer : ICustomSorter
{
    private PropertyInfo _propertyInfo;
    private Type _objectType;

    public string SortMemberPath { get; set; }

    private readonly NumericComparer _comparer = new NumericComparer();

    public Type ObjectType
    {
        get { return _objectType; }
        set
        {
            _objectType = value;

            if (_objectType != null) _propertyInfo = ObjectType.GetProperty(SortMemberPath);
        }
    }

    private int CompareHelper(object x, object y)
    {
        if (_propertyInfo != null)
        {
            var value1 = _propertyInfo.GetValue(x);
            var value2 = _propertyInfo.GetValue(y);

            return _comparer.Compare(value1, value2);
        }

        return 0;
    }

    public int Compare(object x, object y)
    {
        var i = CompareHelper(x, y);

        if (SortDirection == ListSortDirection.Ascending)
            return i;

        return i*-1;
    }

    public ListSortDirection SortDirection { get; set; }
}
 0
Author: ari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:09

Możesz użyć tego w przypadku, gdy dodasz kolumny programowo .

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

"val1" tutaj jest ścieżka wiążąca dla kolumny, którą dodaliśmy, i możesz również użyć innej linii jako drugiego sortowania . jak ten .

        dg_show.Items.SortDescriptions.Add(new System.ComponentModel.SortDescription("val2", System.ComponentModel.ListSortDirection.Ascending));
 -2
Author: ahmedcool166,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-15 01:38:23