You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WPF的DataTemplate中以编程方式添加Interaction Trigger

问题:通过代码实现ComboBox的Interaction Trigger功能

我需要用代码实现以下XAML中ComboBox的Interaction Trigger功能:

<ComboBox ...>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="DropDownClosed">
            <i:InvokeCommandAction Command="{Binding DataContext.DropDownCommand, RelativeSource={RelativeSource Findancestor, AncestorType = { x:Type Window}}}" CommandParameter="{Binding Path=.}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    ...
</ComboBox>

现有创建ComboBox的代码能正常运行,但添加触发器时调用Interaction.GetTriggers(combobox)报错,相关代码片段如下:

//ComboBox
FrameworkElementFactory combobox = new FrameworkElementFactory(typeof(ComboBox));
combobox.SetBinding(ComboBox.SelectedItemProperty, selectedItembinding);
combobox.SetBinding(ComboBox.ItemsSourceProperty, itemsourcebinding);
combobox.SetValue(ComboBox.DisplayMemberPathProperty, columnName.DisplayMemberPathName);
combobox.SetValue(ComboBox.StyleProperty, comboBoxStyle);
combobox.SetValue(ComboBox.ItemContainerStyleProperty, itemContainerStyle);

尝试添加触发器的代码:

//Interaction.Triggers
InvokeCommandAction invokeCommandAction = new InvokeCommandAction { CommandParameter = "{Binding Path=.}" };
Binding binding = new Binding { Path = new PropertyPath("DataContext.DropDownCommand") };
BindingOperations.SetBinding(invokeCommandAction, InvokeCommandAction.CommandProperty, binding);

Microsoft.Xaml.Behaviors.EventTrigger eventTrigger = new Microsoft.Xaml.Behaviors.EventTrigger { EventName = "DropDownClosed" };
eventTrigger.Actions.Add(invokeCommandAction);

TriggerCollection triggers = Interaction.GetTriggers(combobox); // 此处报错
triggers.Add(eventTrigger);

完整方法代码:

private static DataGridTemplateColumn GetComboBoxUniqueColumn(ComboBoxUniqueColumn columnName)  
{
    DataGridTemplateColumn column = new DataGridTemplateColumn();
    column.IsReadOnly = true;
    column.Header = columnName.DisplayColumnName;
    column.Width = columnName.Width;
    column.MinWidth = GetMinWidth(columnName.Width);

    //Binding
    Binding selectedItembinding = new Binding();
    selectedItembinding.Path = new PropertyPath(columnName.SelectedItemPropertyName);
    selectedItembinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;

    Binding itemsourcebinding = new Binding();
    itemsourcebinding.Path = new PropertyPath(string.Format("DataContext.{0}", columnName.ItemSourcePropertyName));
    itemsourcebinding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Window), 1);

    Binding isselectablebinding = new Binding();
    isselectablebinding.Path = new PropertyPath("IsSelectable");

    //Style
    Style comboBoxStyle = Application.Current.Resources["DataGridComboBox"] as Style;

    Style itemContainerStyle = new Style();
    itemContainerStyle.TargetType = typeof(ComboBoxItem);
    itemContainerStyle.BasedOn = Application.Current.Resources["DataGridComboBoxItemContainerStyle"] as Style;
    itemContainerStyle.Setters.Add(new Setter(ComboBoxItem.IsEnabledProperty, isselectablebinding));

    //ComboBox
    FrameworkElementFactory combobox = new FrameworkElementFactory(typeof(ComboBox));
    combobox.SetBinding(ComboBox.SelectedItemProperty, selectedItembinding);
    combobox.SetBinding(ComboBox.ItemsSourceProperty, itemsourcebinding);
    combobox.SetValue(ComboBox.DisplayMemberPathProperty, columnName.DisplayMemberPathName);
    combobox.SetValue(ComboBox.StyleProperty, comboBoxStyle);
    combobox.SetValue(ComboBox.ItemContainerStyleProperty, itemContainerStyle);

    //Interaction.Triggers
    //InvokeCommandAction invokeCommandAction = new InvokeCommandAction { CommandParameter = "{Binding Path=.}" };
    //Binding binding = new Binding { Path = new PropertyPath("DataContext.DropDownCommand") };
    //BindingOperations.SetBinding(invokeCommandAction, InvokeCommandAction.CommandProperty, binding);

    //Microsoft.Xaml.Behaviors.EventTrigger eventTrigger = new Microsoft.Xaml.Behaviors.EventTrigger { EventName = "DropDownClosed" };
    //eventTrigger.Actions.Add(invokeCommandAction);

    //TriggerCollection triggers = Interaction.GetTriggers(??);
    //triggers.Add(eventTrigger);
            
    //Set to DataTemplate
    var datatemplate = new DataTemplate();
    datatemplate.VisualTree = combobox;

    //Set to DataGridTemplateColumn
    column.CellTemplate = datatemplate;

    return column;
}

需要解决如何通过代码重现XAML中的Interaction Trigger功能。


解决方案

问题核心:Interaction.GetTriggers仅适用于已实例化的UI元素,而FrameworkElementFactory是模板生成器,并非实际元素实例。正确做法是通过附加属性直接给工厂设置触发器集合,同时修正绑定逻辑。

修正后的触发器实现代码

替换原注释掉的触发器部分,使用以下代码:

// 创建InvokeCommandAction并设置绑定
InvokeCommandAction invokeCommandAction = new InvokeCommandAction();

// 设置CommandParameter的绑定(不能直接赋值字符串,需创建Binding对象)
Binding commandParamBinding = new Binding { Path = new PropertyPath(".") };
invokeCommandAction.SetBinding(InvokeCommandAction.CommandParameterProperty, commandParamBinding);

// 设置Command的绑定,匹配XAML中查找Window的DataContext逻辑
Binding commandBinding = new Binding
{
    Path = new PropertyPath("DataContext.DropDownCommand"),
    RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Window), 1)
};
invokeCommandAction.SetBinding(InvokeCommandAction.CommandProperty, commandBinding);

// 创建EventTrigger并添加Action
Microsoft.Xaml.Behaviors.EventTrigger eventTrigger = new Microsoft.Xaml.Behaviors.EventTrigger { EventName = "DropDownClosed" };
eventTrigger.Actions.Add(invokeCommandAction);

// 创建触发器集合并添加事件触发器
TriggerCollection triggerCollection = new TriggerCollection();
triggerCollection.Add(eventTrigger);

// 将触发器集合通过附加属性赋值给ComboBox工厂
combobox.SetValue(Interaction.TriggersProperty, triggerCollection);

关键注意点

  • CommandParameter绑定修正:原代码直接赋值"{Binding Path=.}"是字符串,不是绑定,必须创建Binding对象并通过SetBinding设置。
  • Command绑定修正:必须添加RelativeSource指向Window,否则无法找到目标DataContext。
  • 触发器赋值方式:通过SetValue给FrameworkElementFactory设置Interaction.TriggersProperty附加属性,替代Interaction.GetTriggers方法。

替换后运行代码,即可实现与XAML完全一致的Interaction Trigger功能。


内容的提问来源于stack exchange,提问作者Yannick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 09:05:06