i:DataTemplate内部的Interaction.Triggers?

时间:2017-11-10 19:48:31

标签: c# wpf

我一直在使用i:Interaction.Triggers和EventToCommand实现来处理我的VM中的某些控制事件。

<DataGrid ...>
<i:Interaction.Triggers>
    <i:EventTrigger EventName="AutoGeneratingColumn">
        <ui:EventToCommand Command="{Binding Path=DataContext.AutoGeneratingColumnCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
                            PassEventArgsToCommand="True" />

一切正常。然后我需要有多个DataGrids,所以我创建了一个ItemsControl模板,其中包含带有交互触发器的DataGrid。我注意到在这种情况下,触发器无效。

这是一个已知问题吗?我调试了EventToCommand类,它正在调用Attach成员,但它从不调用Invoke。

ItemsControl看起来像:

<ItemsControl>
   <ItemsControl.ItemsTemplate>
<DataGrid ...>
<i:Interaction.Triggers>
    <i:EventTrigger EventName="AutoGeneratingColumn">
        <ui:EventToCommand Command="{Binding Path=DataContext.AutoGeneratingColumnCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
                            PassEventArgsToCommand="True" />

有什么想法吗?我做错了吗?

编辑:

<ItemsControl Grid.Row="2" ItemsSource="{Binding StoredProcedureResults}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <DataGrid EnableColumnVirtualization="True" EnableRowVirtualization="True" SelectionMode="Extended" SelectionUnit="CellOrRowHeader"
                        CanUserAddRows="False" CanUserDeleteRows="False" IsReadOnly="True" BorderThickness="0,0,0,0" ItemsSource="{Binding}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="AutoGeneratingColumn">
                        <UI:EventToCommand Command="{Binding Path=DataContext.AutoGeneratingColumnCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
                                            PassEventArgsToCommand="True" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="LoadingRow">
                        <UI:EventToCommand Command="{Binding Path=DataContext.LoadingRowCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
                                            PassEventArgsToCommand="True" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </DataGrid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

1 个答案:

答案 0 :(得分:1)

这是System.Windows.Interactivity EventTrigger问题和某些情况的组合。

Interactivity.EventTrigger无法处理在FrameworkElement.Loaded事件之前触发的事件

它在内部使用关联对象的Loaded事件来为除Loaded事件本身之外的所有事件附加事件处理程序。来自OnAttached的{​​{1}}方法是从EventToCommand调用的,它实际上将TriggerAction.Attach附加到关联对象(此处为DataGrid)。 TriggerAction上的AssociatedObject属性不是DependencyProperty,而TriggerAction继承自TriggerAction,此方法会执行freezable相关内容(调用Freezable和{{1} })。实际的事件处理程序尚未附加。

DataGrid AutoGeneratingColumn和LoadingRow

如果在初始化DataGrid时可以确定ItemsSource(DataGrid可以确定需要生成哪些列和行),则这些事件在Loaded事件之前触发。我假设当你的DataGrid不是DataTemplate的一部分时,它的ItemsSource被绑定到VM上的一个属性,在初始化DataGrid时它的值为null。将DataGrid移动到DataTemplate后,当您为ItemsControl设置WritePreamble属性并为每个ItemControl的Item初始化DataGrids时,可以在初始化期间确定DataGrid的WritePostscript这些事件在Loaded事件之前触发。如果您允许用户向DataGrid添加行(ItemsSource为false,ItemsSource为true),则IsReadOnly将在CanUserAddRows变为true后执行,并且用户添加了行。

要使其工作,您必须不要在DataTemplate中设置DataGrid的LoadingRowCommand(基本上删除DataGrid.IsLoaded),等待Loaded事件然后设置它。我说这违背了项目模板的想法(并且有一种很好的方法可以做到这一点吗?),所以我会按照你在评论中的建议去寻找这两个事件的附加行为。