我知道如何使用代码隐藏方法处理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中的Header click事件?
答案 0 :(得分:1)
您需要在标题样式中设置触发器。交互触发器和行为通常不能在样式中设置,因为TriggerCollection和BehaviorCollection类是密封的,因此您无法在XAML中声明它们。但是,用户vspivak发布了a workaround for this on the wordpress site,它基本上创建了自己的列表,并使它们与交互列表中的列表保持同步:
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>
有点克服,但它确实有效。