当底层的视图模型需要时,我如何在视图上设置WPF事件触发器?

28

这是场景:

我有以下用户控件,其想法是其视图模型应该能够向视图发信号以表明它需要“激活 Glow”,从而播放 Storyboard。

<UserControl x:Class="View.UnitView"  ... >
   ...
    <Storyboard x:Key="ActivateGlow">
       ...
    </Storyboard>
    ...
    <!-- INVALID BINDING! Not Dependancy Object-->
    <EventTrigger RoutedEvent="{Binding OnActivateGlow}"> 
       <BeginStoryboard Storyboard="{StaticResource ActivateGlow}"/>
    </EventTrigger>
</UserControl>

在 UnitView 的后端代码中,我有以下内容:

public event EventHandler ActivateGlow;

而在MVVM中非常常见的是,我有以下的DataTemplate用于UnitViewModel:

<DataTemplate DataType="{x:Type vm:UnitViewModel}">
    <vw:UnitView d:DesignWidth="150" d:DesignHeight="100" />
</DataTemplate>

最重要的问题是,我如何设置某些内容,以便视图模型可以触发OnActivateGlow事件?

4个回答

13

更新:根据评论中提到的Firoso,您应该能够(我认为- 未经测试)使用混合行为组件来满足您的要求。

除了下载和安装SDK外,还需要获取Expression Blend示例库的副本(您需要从以下链接中单击“下载”): Expression Blend samples

此库包含一个名为“DataEventTrigger”的预构建触发器,您可以使用它来触发响应于ViewModel上声明的事件的操作。

Blend SDK已经具备(据我所知)拼图的另一部分-它已经包括允许您控制故事板的动作。此操作的名称为“ControlStoryboardAction”。

您最终应该得到类似于这样的一些XAML:

    <i:Interaction.Triggers>
        <samples:DataEventTrigger EventName="YourEvent">
            <im:ControlStoryboardAction Storyboard="{StaticResource Storyboard1}" 
                   ControlStoryboardOption="Play"/>
        </samples:DataEventTrigger>
    </i:Interaction.Triggers>

将“YourEvent”替换为您在视图模型上定义的事件名称,并将“Storyboard1”替换为您的故事板的名称。当然,名称必须完全匹配。

这里是使用的XAML命名空间定义:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
xmlns:im="clr-namespace:Microsoft.Expression.Interactivity.Media;assembly=Microsoft.Expression.Interactions"
xmlns:samples="clr-namespace:Expression.Samples.Interactivity;assembly=Expression.Samples.Interactivity"

编辑前的原帖:

建议您研究一下Expression Blend行为:

信息

Blend SDK

有关行为的视频


1
嗯...据我理解,你的问题围绕着如何让视图模型触发视图上的一些操作是吗?你可以使用Blend行为来实现这种功能。不过我不确定你是否应该以事件的方式进行建模。但是你可以通过在视图模型上引发一个事件,在视图上截获事件,并对事件作出响应来完成一些操作。所以,在这种情况下,你可以在视图模型上引发一个“requestglow”事件,在视图上截获它,并执行一个BeginStoryboard动作。行为就是为了在没有代码后台的情况下实现视图模型和视图之间的交互而存在的。 - Phil
这里有一个视频,展示了混合行为的一些功能:http://channel9.msdn.com/shows/toolshed/Tool-Shed-Tooltip-27-Expression-Blend-3-Behaviors/顺便说一句,如果你正在使用MVVM,我会说,你真的应该看看行为,即使你最终不会在当前需求中使用它。这对于MVVM来说是一件大事! - Phil
1
firoso,请看一下这个页面:http://expressionblend.codeplex.com/其中包含了一个混合行为库。它有一个名为“DataEventTrigger”的触发器,可以在与您的数据上下文绑定的对象上发生事件时触发动作。 - Phil
我理解的是否正确,在没有Blend的情况下,使用WPF 3.5(因为我认为它仅适用于2012和13年),我的最佳(也是唯一)选择就是像qntmfred的帖子中建议的那样使用属性触发器? - James Joshua Street
这似乎已经被弃用或不再受支持 - 是否有替代方案或更为现代化的解决方案? - JazziJeff
显示剩余9条评论

7

你也可以在你的ViewModel上放置一个布尔类型的IsGlowing属性,并在样式中使用数据触发器。

<Rectangle.Style>  
    <Style TargetType="{x:Type Rectangle}">  
        <Style.Triggers>  
            <DataTrigger Binding="{Binding Path=IsGlowing}" Value="True">  
                <DataTrigger.EnterActions>  
                    <BeginStoryboard>  
                        <Storyboard>  
                            ...  
                        </Storyboard>  
                    </BeginStoryboard>  
                </DataTrigger.EnterActions>  
            </DataTrigger>  
        </Style.Triggers>  
    </Style>  
</Rectangle.Style>  

0

我认为您需要绑定到一个RoutedEvent实例,而不是CLR事件。

虽然我没有尝试过这种方法,但下面这样应该可以工作:

public class UnitView
{
    public static readonly RoutedEvent ActivateGlowEvent
        = EventManager.RegisterRoutedEvent(
              "ActivateGlow", RoutingStrategy.Bubble,
              typeof(RoutedEventHandler), typeof(UnitView)
          );

    public void RaiseActivateGlowEvent()
    {
        RaiseEvent(new RoutedEventArgs(ActivateGlowEvent));
    }
}

2
好的,那回答了我问题的一半,现在我该如何让视图模型触发ActivateGlow? - Firoso
4
为了添加RoutedEvent和RaiseEvent,需要让UnitView继承自WPF控件。问题要求的是ViewModel,而不是控件。 - midspace

0
我发现解决这个问题的一种方法是在包含上述控件的DataTemplate上使用数据触发器... 但这可能不是最好的方法。 我仍然开放接受更好的想法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接