使用EventTrigger引发附加事件

时间:2013-07-25 23:52:11

标签: c# wpf xaml routed-events

我有一个类MyAttachedEventClassAquarium,用于定义从MSDN文档中获取的自定义附件。我有一个Window在XAML中使用EventTrigger来挂钩要在Window的viewmodel上处理的事件。视图模型被声明为本地资源。

<Window.Resources>
    <local:WinVM x:Key="myWinVM" />
</Window.Resources>
<i:Interaction.Triggers>
    <i:EventTrigger EventName="NeedsCleaning" SourceName="MyAttachedEventClassAquarium">
        <ei:CallMethodAction MethodName="MyCustomEventWasRaised" TargetObject="{StaticResource myWinVM}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

我使用窗口自己的RaiseEvent从按钮按下处理程序引发附加事件:

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        ((Window1)((Grid)((Button)sender).Parent).Parent).RaiseEvent(new RoutedEventArgs(MyAttachedEventClassAquarium.NeedsCleaningEvent));
    }

为什么我的处理程序不会被调用?

提前致谢。

2 个答案:

答案 0 :(得分:0)

(已编辑)

这种挂钩事件以便ViewModel处理的方法看起来不太可维护。要对其进行故障排除,最好使用Snoop实用程序将视觉和逻辑树分开,以确保您正在构建的对象(所有这些对象都实现了RaiseEvent方法)实际上是您想要的对象。

您可能还需要将SourceName参数定义为Window上的资源。

这些是猜测,它们描述了一种与MVVM模式所要求的消息传递方法截然不同的方法。不要像这样深入挖掘你的逻辑树,这是一种非常脆弱的方法,而是使用下面和其他地方找到的记录和验证的模式:访问DataContext的{​​{1}}并直接调用VM方法。或者,在ViewModel类中实现Window并将命令绑​​定到它。

这第一种方法打破了MVVM最纯粹的方法,但它会起作用。

ICommand

另一种方法是在ViewModel类上实现private void button1_Click(object sender, RoutedEventArgs e) { var VM = this.DataContext As WinVM; if (VM != null) { VM.MyCustomEventWasRaised(); } } ,并在View中配置ICommand以使用该命令:

Button

后者将在大多数情况下消除对任何XAML代码隐藏代码的需求。

答案 1 :(得分:0)

在我看来,问题是SourceName - 需要是一个实例,而不是类名?如果我将事件源添加到可视树中作为“水族馆”,并将“SourceName”更改为“aquarium”,则会触发该操作:

<Window>
    <Window.Resources>
        <local:WinVM x:Key="myWinVM" />
    </Window.Resources>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="NeedsCleaning" SourceName="aquarium">
            <ei:CallMethodAction MethodName="MyCustomEventWasRaised" TargetObject="{StaticResource myWinVM}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>

    <StackPanel>
        <my:MyAttachedEventClassAquarium x:Name="aquarium" />
        <Button x:Name="button" Click="button1_Click" Content="Raise Event" />
    </StackPanel>

</Window>

private void button1_Click(object sender, RoutedEventArgs e)
{
    aquarium.RaiseEvent(new RoutedEventArgs(MyAttachedEventClassAquarium.NeedsCleaningEvent));
}

只是添加:如果我在水族馆对象上引发事件,上面的方法似乎只能 使用与EventTrigger的{{相同的水族馆对象1}}。这似乎与System.Windows.Interactivity.EventTrigger类(bug?)有关,因为当我使用DependencyObject.Triggers.EventTrigger类时,事件会像你期望的那样起泡。