如何在 MVVM 上下文中处理数据网格中的标头单击事件

本文关键字:网格 事件 单击 数据网 数据 MVVM 上下文 处理 | 更新日期: 2023-09-27 18:36:41

我知道如何使用代码隐藏方法处理 DataGrid WPF 中的标头单击事件:

<DataGrid>
    <DataGrid.Resources>
        <Style TargetType="DataGridColumnHeader">
            <EventSetter Event="Click" Handler="columnHeader_Click" />
        </Style>
    </DataGrid.Resources>
</DataGrid>

但是,我想在 MVVM 的上下文中处理此事件。我试图通过System.Windows.Interactivity来处理,但我无法弄清楚我应该在EventName里面写什么:

<DataGrid>
   <i:Interaction.Triggers>
      <i:EventTrigger EventName="What event can I use?"
   </i:Interaction.Triggers>
</DataGrid>

我见过诸如ColumnReorderedColumnReordering之类的事件,但它不适用。

如何在 MVVM 上下文中处理 DataGrid WPF 中的标头单击事件?

如何在 MVVM 上下文中处理数据网格中的标头单击事件

您需要在标头样式中设置触发器。通常不能在样式中设置交互触发器和行为,因为 TriggerCollection 和 BehaviorCollection 类是密封的,因此不能在 XAML 中声明它们。但是,用户vspivak在wordpress网站上发布了一个解决方法,该站点基本上创建了自己的列表,并使它们与交互列表中的列表保持同步:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Interactivity;
namespace YourApplication
{
    /// <summary>
    /// <see cref="FrameworkTemplate"/> for InteractivityElements instance
    /// <remarks>Subclassed for forward compatibility, perhaps one day <see cref="FrameworkTemplate"/> </remarks>
    /// <remarks>will not be partially internal</remarks>
    /// </summary>
    public class InteractivityTemplate : DataTemplate
    {
    }
    /// <summary>
    /// Holder for interactivity entries
    /// </summary>
    public class InteractivityItems : FrameworkElement
    {
        private List<Behavior> _behaviors;
        private List<System.Windows.Interactivity.TriggerBase> _triggers;
        /// <summary>
        /// Storage for triggers
        /// </summary>
        public List<System.Windows.Interactivity.TriggerBase> Triggers
        {
            get
            {
                if (_triggers == null)
                    _triggers = new List<System.Windows.Interactivity.TriggerBase>();
                return _triggers;
            }
        }
        /// <summary>
        /// Storage for Behaviors
        /// </summary>
        public List<Behavior> Behaviors
        {
            get
            {
                if (_behaviors == null)
                    _behaviors = new List<Behavior>();
                return _behaviors;
            }
        }
        #region Template attached property
        public static InteractivityTemplate GetTemplate(DependencyObject obj)
        {
            return (InteractivityTemplate)obj.GetValue(TemplateProperty);
        }
        public static void SetTemplate(DependencyObject obj, InteractivityTemplate value)
        {
            obj.SetValue(TemplateProperty, value);
        }
        public static readonly DependencyProperty TemplateProperty =
            DependencyProperty.RegisterAttached("Template",
            typeof(InteractivityTemplate),
            typeof(InteractivityItems),
            new PropertyMetadata(default(InteractivityTemplate), OnTemplateChanged));
        private static void OnTemplateChanged(
            DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            InteractivityTemplate dt = (InteractivityTemplate)e.NewValue;
#if(!SILVERLIGHT)
            dt.Seal();
#endif
            InteractivityItems ih = (InteractivityItems)dt.LoadContent();
            BehaviorCollection bc = Interaction.GetBehaviors(d);
            System.Windows.Interactivity.TriggerCollection tc = Interaction.GetTriggers(d);
            foreach (Behavior behavior in ih.Behaviors)
                bc.Add(behavior);
            foreach (System.Windows.Interactivity.TriggerBase trigger in ih.Triggers)
                tc.Add(trigger);
        }
        #endregion
    }
}

有了这个,就很容易将其应用于 ColumnHeaderStyle:

    <DataGrid.ColumnHeaderStyle>
        <Style TargetType="DataGridColumnHeader">
            <Setter Property="local:InteractivityItems.Template">
                <Setter.Value>
                    <local:InteractivityTemplate>
                        <local:InteractivityItems>
                            <local:InteractivityItems.Triggers>
                                <i:EventTrigger EventName="Click" >
                                    <i:InvokeCommandAction Command="{Binding DataContext.YourCommand,
                                        RelativeSource={RelativeSource AncestorType=DataGrid}}" />
                                </i:EventTrigger>
                            </local:InteractivityItems.Triggers>
                        </local:InteractivityItems>
                    </local:InteractivityTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGrid.ColumnHeaderStyle>

有点笨拙,但它有效。