【问题标题】:How can I apply a custom sort for a WPF DataGrid from a style?如何从样式中为 WPF DataGrid 应用自定义排序?
【发布时间】:2019-08-29 22:10:55
【问题描述】:

我想将一种样式应用于DataGridDataGrid 需要运行我的自定义排序代码,而不是默认的 DataGrid 排序。我尝试的解决方案如下:

<Style TargetType="{x:Type DataGrid}" x:Key="FilteredDataGrid">
    <EventSetter Event="Sorting" Handler="DataGrid_Sorting"/>
</Style>

在代码隐藏中:

private void DataGrid_Sorting(object sender, DataGridSortingEventArgs e) {

    e.Handled = true;

    //Here is where I put the code for my custom sort.

}//DataGrid_Sorting

但是,此代码无法构建。在我看来,因为DataGrid.Sorting 事件不是RoutedEvent,所以它不能在EventSetter 中使用。

如何为应用了我的样式的任何 DataGrid 自定义排序?

【问题讨论】:

  • 通常,您不会对DataGrid 而是对绑定到ItemsSourceCollectionView 进行排序
  • 我并不真正接受这个问题。应该根据需求做出决定,一种风格是否是实施某事的正确场所。那么从用户的角度来看,您的实际需求是什么?为什么您认为样式是实现它的正确方法?
  • @grek40 我 am 对 ItemSource 进行排序,而不是对实际行进行排序。但我想通过单击列标题来触发该排序,这会导致默认排序发生。
  • 所以基本上每列都需要一个自定义排序函数,并且当列有多个相同等级的值时,你有一些后续的排序逻辑?
  • @grek40 不,DataGrid 绑定到的集合来自服务器并由服务器排序(在某些情况下,我们谈论的是 1000 行)。我需要调用服务器对集合进行排序。为什么我使用样式?我的项目中有 100 多个 DataGrid,并且这种样式会自动应用于具有特定集合类型作为 ItemSource 的样式。除了自定义排序之外,该样式还有更多功能。

标签: wpf sorting datagrid


【解决方案1】:

当您只有“正常”事件时,有一种解决方法可以提供路由事件:

创建一个控制事件转发的附加属性和一个替换原始事件的附加事件。为此,请创建一个类 DataGridEx(您喜欢的任何类名称)作为附加属性 (DataGridEx.EnableSortingEvent) 和事件 (DataGridEx.Sorting) 的容器。

另外,创建一个自定义RoutedEventArgs 类,用于转发原始排序事件参数

public class DataGridExSortingEventArgs : RoutedEventArgs
{
    public DataGridExSortingEventArgs(RoutedEvent routedEvent, DataGridSortingEventArgs sourceEventArgs) : base(routedEvent)
    {
        SourceEventArgs = sourceEventArgs;
    }

    public DataGridSortingEventArgs SourceEventArgs { get; set; }
}

public static class DataGridEx
{
    public static bool GetEnableSortingEvent(DependencyObject obj)
    {
        return (bool)obj.GetValue(EnableSortingEventProperty);
    }

    public static void SetEnableSortingEvent(DependencyObject obj, bool value)
    {
        obj.SetValue(EnableSortingEventProperty, value);
    }

    // Setting this property to true enables the event forwarding from the DataGrid.Sorting event to the DataGridEx.Sorting RoutedEvent
    public static readonly DependencyProperty EnableSortingEventProperty = DependencyProperty.RegisterAttached(
        "EnableSortingEvent",
        typeof(bool),
        typeof(DataGridEx),
        new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnEnableSortingChanged)));

    private static void OnEnableSortingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is DataGrid dg)
        {
            if ((bool)e.NewValue)
                dg.Sorting += Dg_Sorting;
            else
                dg.Sorting -= Dg_Sorting;
        }
    }

    // When DataGrid.Sorting is called and DataGridEx.EnableSortingEvent is true, raise the DataGridEx.Sorting event
    private static void Dg_Sorting(object sender, DataGridSortingEventArgs e)
    {
        if (sender is DataGrid dg && GetEnableSortingEvent(dg))
        {
            dg.RaiseEvent(new DataGridExSortingEventArgs(SortingEvent, e));
        }
    }

    // When DataGridEx.EnableSortingEvent is true, the DataGrid.Sorting event will be forwarded to this routed event
    public static readonly RoutedEvent SortingEvent = EventManager.RegisterRoutedEvent(
        "Sorting",
        // only effective on the DataGrid itself
        RoutingStrategy.Direct,
        typeof(RoutedEventHandler),
        typeof(DataGridEx));

    public static void AddSortingHandler(DependencyObject d, RoutedEventHandler handler)
    {
        if (d is DataGrid dg)
            dg.AddHandler(SortingEvent, handler);
    }

    public static void RemoveSortingHandler(DependencyObject d, RoutedEventHandler handler)
    {
        if (d is DataGrid dg)
            dg.RemoveHandler(SortingEvent, handler);
    }
}

现在使用您的风格(local 是定义 DataGridEx 的命名空间的 xmlns):

<Style TargetType="DataGrid">
    <Setter Property="local:DataGridEx.EnableSortingEvent" Value="True"/>
    <EventSetter Event="local:DataGridEx.Sorting" Handler="DataGrid_Sorting"/>
</Style>

处理程序

private void DataGrid_Sorting(object sender, RoutedEventArgs e)
{
    if (e is DataGridExSortingEventArgs args)
    {
        // will prevent datagrid default sorting
        args.SourceEventArgs.Handled = true;
    }

    // More stuff
}

我希望这是您所需要的。不得不刷新我对附加内容的记忆:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 2021-04-02
    • 2012-04-01
    • 2011-12-26
    • 2012-05-01
    • 1970-01-01
    相关资源
    最近更新 更多