如何在MVVM上下文中处理DataGrid中的Header click事件?

时间:2016-02-29 17:02:06

标签: c# wpf events mvvm datagrid

我知道如何使用代码隐藏方法处理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中的Header click事件?

1 个答案:

答案 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>

有点克服,但它确实有效。