簡體   English   中英

對於具有轉換器的枚舉,WPF數據網格排序失敗

[英]WPF datagrid sorting fails for enum with converter

我有一個帶有以下列的DataGrid ,它使用轉換器綁定到名為Typeenum

<DataGridTextColumn Header="Type" 
 Binding="{Binding Path=Type,Converter={StaticResource EnumStringConverter}}" />

它正確顯示轉換后的值。 但它在排序方面失敗了。

升序排序出錯了

降序排序也出錯了!

升序排序的正確順序應該是Cash, Debt Security and Gold或者是降序排序。

枚舉定義為

enum SomeType
{   
    Cash = 0,
    Gold = 1,

    // few more values ...

    DebtSecurity = 6,
}

我也嘗試使用SortMemberPath="Type"作為列,但仍然給出相同的結果。 我錯過了一些非常基本的東西嗎?

經過廣泛的搜索並找到部分答案,我可以合並可用的答案來解決這種通用要求。

因此,如果您想通過枚舉轉換后的值啟用排序。

1)添加以下的enerted-enum-sorting類

/// <summary>
/// Allows a grid to be sorted based upon the converted value.
/// </summary>
public static class GridEnumSortingBehavior
{
    #region Properties

    public static readonly DependencyProperty UseBindingToSortProperty =
       DependencyProperty.RegisterAttached("UseBindingToSort", typeof(bool), typeof(GridEnumSortingBehavior),
                                           new PropertyMetadata(UseBindingToSortPropertyChanged));

    #endregion

    public static void SetUseBindingToSort(DependencyObject element, bool value)
    {
        element.SetValue(UseBindingToSortProperty, value);
    }

    #region Private events

    private static void UseBindingToSortPropertyChanged(DependencyObject element, DependencyPropertyChangedEventArgs e)
    {
        var grid = element as DataGrid;
        if (grid == null)
        {
            return;
        }

        var canEnumSort = (bool)e.NewValue;
        if (canEnumSort)
        {
            grid.Sorting += GridSorting;
        }
        else
        {
            grid.Sorting -= GridSorting;
        }
    }

    private static void GridSorting(object sender, DataGridSortingEventArgs e)
    {
        var boundColumn = e.Column as DataGridBoundColumn;
        if (boundColumn == null)
        {
            return;
        }

        // Fetch the converter,binding prop path name, if any
        IValueConverter converter = null;
        string bindingPropertyPath = null;
        if (boundColumn.Binding == null)
        {
            return;
        }
        var binding = boundColumn.Binding as Binding;
        if (binding == null || binding.Converter == null)
        {
            return;
        }
        converter = binding.Converter;
        bindingPropertyPath = binding.Path.Path;
        if (converter == null || bindingPropertyPath == null)
        {
            return;
        }

        // Fetch the collection
        var dataGrid = (DataGrid)sender;
        var lcv = (ListCollectionView)CollectionViewSource.GetDefaultView(dataGrid.ItemsSource);
        if (lcv == null || lcv.ItemProperties == null)
        {
            return;
        }

        // Fetch the property bound to the current column (being sorted)
        var bindingProperty = lcv.ItemProperties.FirstOrDefault(prop => prop.Name == bindingPropertyPath);
        if (bindingProperty == null)
        {
            return;
        }

        // Apply custom sort only for enums types
        var bindingPropertyType = bindingProperty.PropertyType;
        if (!bindingPropertyType.IsEnum)
        {
            return;
        }

        // Apply a custom sort by using a custom comparer for enums
        e.Handled = true;
        ListSortDirection directionToSort = boundColumn.SortDirection != ListSortDirection.Ascending
                                                 ? ListSortDirection.Ascending
                                                 : ListSortDirection.Descending;
        boundColumn.SortDirection = directionToSort;
        lcv.CustomSort = new ConvertedEnumComparer(converter, directionToSort, bindingPropertyType, bindingPropertyPath);
    }

    #endregion
}

2)添加一個自定義比較器,根據轉換后的值比較枚舉值

/// <summary>
/// Converts the value of enums and then compares them
/// </summary>
public class ConvertedEnumComparer : IComparer
{

    #region Fields

    private readonly Type _enumType;
    private readonly string _enumPropertyPath;
    private readonly IValueConverter _enumConverter;
    private readonly ListSortDirection _directionToSort;

    #endregion

    public ConvertedEnumComparer(IValueConverter enumConverter, ListSortDirection directionToSort, Type enumType, string enumPropertyPath)
    {
        _enumType = enumType;
        _enumPropertyPath = enumPropertyPath;
        _enumConverter = enumConverter;
        _directionToSort = directionToSort;
    }

    #region IComparer implementation

    public int Compare(object parentX, object parentY)
    {
        if (!_enumType.IsEnum)
        {
            return 0;
        }

        // extract enum names from the parent objects
        var enumX = TypeDescriptor.GetProperties(parentX)[_enumPropertyPath].GetValue(parentX);
        var enumY = TypeDescriptor.GetProperties(parentY)[_enumPropertyPath].GetValue(parentY);

        // convert enums
        object convertedX = _enumConverter.Convert(enumX, typeof(string), null, Thread.CurrentThread.CurrentCulture);
        object convertedY = _enumConverter.Convert(enumY, typeof(string), null, Thread.CurrentThread.CurrentCulture);

        // compare the converted enums
        return _directionToSort == ListSortDirection.Ascending
                               ? Comparer.Default.Compare(convertedX, convertedY)
                               : Comparer.Default.Compare(convertedX, convertedY) * -1;
    }

    #endregion
}

3)最后在任何DataGrid上使用它只需將行為標記為True

<DataGrid ItemsSource="{Binding YourDataCollectionWithEnumProperty}" 
yourbehaviors:GridEnumSortingBehavior.UseBindingToSort="True" >

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM