[英]WPF datagrid sorting fails for enum with converter
I have a DataGrid
with the following column, which binds to an enum
named Type
with a converter. 我有一个带有以下列的
DataGrid
,它使用转换器绑定到名为Type
的enum
。
<DataGridTextColumn Header="Type"
Binding="{Binding Path=Type,Converter={StaticResource EnumStringConverter}}" />
It displays the converted values properly. 它正确显示转换后的值。 But it fails at sorting.
但它在排序方面失败了。
The correct order for ascending sort should have been Cash, Debt Security and Gold
or reverse for descending sort. 升序排序的正确顺序应该是
Cash, Debt Security and Gold
或者是降序排序。
The Enum is defined as 枚举定义为
enum SomeType
{
Cash = 0,
Gold = 1,
// few more values ...
DebtSecurity = 6,
}
I have also tried to use the SortMemberPath="Type"
for the column but still gives the same result. 我也尝试使用
SortMemberPath="Type"
作为列,但仍然给出相同的结果。 Am I missing something very basic here? 我错过了一些非常基本的东西吗?
After extensive searching and find some answers in parts, I could merge the available answers to solve a generic requirement of this sort. 经过广泛的搜索并找到部分答案,我可以合并可用的答案来解决这种通用要求。
So, if you want to enable sorting by your enum's converted values. 因此,如果您想通过枚举转换后的值启用排序。
1) Add the following conveerted-enum-sorting class 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) Add a custom comparer that compares the enum values based on their converted values 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) Finally to use this on any DataGrid
simply mark the behavior as True
3)最后在任何
DataGrid
上使用它只需将行为标记为True
<DataGrid ItemsSource="{Binding YourDataCollectionWithEnumProperty}"
yourbehaviors:GridEnumSortingBehavior.UseBindingToSort="True" >
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.