[英]WPF Multiple Converter calls after sorting DataGrid on Cell Click
[英]WPF datagrid sorting fails for enum with converter
我有一個帶有以下列的DataGrid
,它使用轉換器綁定到名為Type
的enum
。
<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.