WPF 在 DataTemplate 中以编程方式添加交互触发器

问题描述 投票:0回答:1

我想添加一个交互触发器,如下面的 xaml 示例所示:

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

我尝试了这个工作代码(直到添加 Interaction.Trigger):

//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); <= this raises an error
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 代码。

wpf eventtrigger programmatically-created
1个回答
0
投票

您可以推迟创建触发器并将其放入例如

Loaded
的事件处理程序中。

将此添加到创建

DataTemplate
的方法中:

combobox.AddHandler(ComboBox.LoadedEvent, new RoutedEventHandler(Cmb_Loaded));
.

因此您可以在事件处理程序中附加触发器,您可以在其中访问

ComboBox

private static void Cmb_Loaded(object sender, RoutedEventArgs e)
{
    if (sender is ComboBox cmb)
    {
        var invokeCommandAction = new InvokeCommandAction { CommandParameter = "{Binding Path=.}" };
        var binding = new Binding { Path = new PropertyPath("DataContext.DropDownCommand"), RelativeSource=new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Window), 1) };
        BindingOperations.SetBinding(invokeCommandAction, InvokeCommandAction.CommandProperty, binding);

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

        TriggerCollection triggers = Interaction.GetTriggers(cmb);
        triggers.Add(eventTrigger);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.