2

我有一个类,MyAttachedEventClassAquarium它定义了一个从 MSDN 文档中获取的自定义附件。我有一个在 XAMLWindow中使用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));
    }

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

提前致谢。

B.

4

2 回答 2

0

(已编辑)

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

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

这些都是猜测,它们描述的消息传递方法与 MVVM 模式所要求的完全不同。与其像那样挖掘逻辑树,这是一种非常脆弱的方法,不如使用下面和其他地方的记录和证明的模式:访问DataContext你的Window并直接调用 VM 方法。或者,ICommand在您的 ViewModel 类中实现一个并将命令绑​​定到它。

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

private void button1_Click(object sender, RoutedEventArgs e)
    {
       var VM = this.DataContext As WinVM;

       if (VM != null) 
       {
         VM.MyCustomEventWasRaised();
       }
    }

ICommand另一种方法是在您的 ViewModel 类上实现一个,并Button在 View 中配置它以使用以下命令:

<Button x:Name="Button1" Command="{Binding NeedsCleaning}" />

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

于 2013-07-26T00:31:27.850 回答
0

在我看来问题是SourceName——这需要是一个实例,而不是类名?如果我将事件源作为“aquarium”添加到可视化树中,并将“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 相同的水族馆对象时才有效SourceName。这似乎与System.Windows.Interactivity.EventTrigger类(错误?)有关,因为当我使用DependencyObject.Triggers.EventTrigger类时,事件会像您期望的那样冒泡。

于 2013-07-26T19:31:42.777 回答