如何在 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>
我见过诸如ColumnReordered
,ColumnReordering
之类的事件,但它不适用。
如何在 MVVM 上下文中处理 DataGrid WPF 中的标头单击事件?
您需要在标头样式中设置触发器。通常不能在样式中设置交互触发器和行为,因为 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>
有点笨拙,但它有效。