2

基本上,我得到的是一个简单的警报消息设置。有一个单独的警报视图,其中一些数据绑定到虚拟机的文本和颜色(绿色表示成功,红色表示错误等)。

<Border Margin="0 0 0 20" Background="{Binding Path=BackgroundColor}" BorderBrush="#D4D4D4" BorderThickness="1" CornerRadius="8">
    <Border.Effect>
        <DropShadowEffect Color="DarkGray"/>
    </Border.Effect>
<Grid >
        <Button Content="X" HorizontalAlignment="Left" 
            Margin="268,10,0,0" VerticalAlignment="Top" Width="20" RenderTransformOrigin="-0.48,0.727"/>
        <TextBlock x:Name="Message" 
           Foreground="White" FontWeight="SemiBold" FontSize="13px"
           Text="{Binding Path=Message}" 
           HorizontalAlignment="Left" Width="250"
           TextWrapping="Wrap"
           VerticalAlignment="Center" RenderTransformOrigin="-4.395,-0.038" Margin="7,13,0,25"/>
    </Grid>
</Border>

目标是在您单击“X”按钮时让它们消失,并带有漂亮的淡入淡出动画。我有一个故事板来处理褪色:

<UserControl.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
        <BeginStoryboard>
            <Storyboard>
                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
                    <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                    <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
                </DoubleAnimationUsingKeyFrames>
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</UserControl.Triggers>

现在,我想做的是让 Caliburn.MicroCompleted使用一种关闭实际视图的方法将 Caliburn.Micro 挂钩到情节提要的事件中(在另一个视图中有这些警报的可绑定集合,以便警报将堆叠然后在用户的愿望)。

起初我尝试过这样的事情,认为它与我的任何其他绑定一样工作:

<Storyboard cal:Message.Attach="[Event Completed] = [Action DismissMessage($source, $eventArgs)]">
<!-- rest of the codez... -->

但出现以下错误:

Cannot attach type "ActionMessage" to type "Storyboard". Instances of type "ActionMessage" can only be attached to objects of type "FrameworkElement".

我猜这很有意义......但是处理这种绑定的最佳方法是什么?我的思绪不可避免地开始徘徊于尝试一些 hacky 解决方案,例如从视图的代码隐藏中调用视图模型,但这似乎违反了 MVVM。

有什么建议么?

4

3 回答 3

4

我认为避免查看代码背后的最佳方法是使用StoryboardCompletedTriggerBlend 交互库中的一个:

首先在您的 xaml 中包含正确的引用:

xmlns:i="http://schemas.microsoft.com/expression/2010/
xmlns:ie="http://schemas.microsoft.com/expression/2010/interactions"   

然后将您的交互触发器添加到您的视图并将其操作设置为CallMethodAction

<i:Interaction.Triggers>
  <ie:StoryboardCompletedTrigger Storyboard="{StaticResource MyStoryboard}">
    <ie:CallMethodAction MethodName="DismissMessage" TargetObject="{Binding}"/>
  </ie:StoryboardCompletedTrigger>
</i:Interaction.Triggers>
于 2015-03-10T15:33:42.190 回答
2

正如我所评论的,一个更简单的出路可能是聚合器。

完成StoryBoard后,您可以通过聚合器(或特定的对话框聚合器)触发事件并在 VM 中处理该事件以关闭对话框

例如,如果您没有聚合器,您将需要提供聚合器的东西(不确定您是否使用 DI)

public static DialogEventAggregatorProvider  
{
    public static EventAggregator { get; set; } // Obviously instantiate this, I'll leave the code out for brevity
}

在您看来代码隐藏:

public SomeView : UserControl
{
    private void StoryBoard_Completed(object sender, SomeEventArgs e)
    {
        DialogEventAggregatorProvider.EventAggregator.Publish(new CloseDialogMessage()); // Add some args or what have you if it helps identify what dialog to close, but try not to break MVVM ;)
    }
}

在虚拟机中

public SomeViewModel : Screen, IHandle<CloseDialogMessage>
{
    public SomeViewModel() 
    {
        // Don't forget to subscribe or you'll be scratching your head
        DialogEventAggregatorProvider.EventAggregator.Subscribe(this);
    }

    public void Handle(CloseDialogMessage message) 
    { 
        // if(message.HasSomeValue) Here you could check the type of message etc.
           TryClose();
    }
}

它不是那么漂亮,但只要你保持通用的实现,你就可以在不违反 MVVM 原则的情况下逃脱

于 2013-02-25T15:38:03.873 回答
0

您可以使用 Marlon Grech 附加命令行为库将该事件绑定到命令。

该库可以从这里下载:http: //marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/

于 2013-02-22T19:09:20.077 回答