基本上,我得到的是一个简单的警报消息设置。可以看到各个警报,其中一些数据绑定到VM的文本和颜色(成功为绿色,错误为红色等)。
<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.Micro用故事板Completed
事件挂钩,用一种方法来模仿实际视图(在另一个视图中有一个可绑定的这些警报集合,以便警报将堆叠,然后根据用户的愿望被解雇。)
我最初尝试过类似的东西,认为它与我的其他任何绑定都一样:
<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解决方案,比如从视图的代码隐藏中调用viewmodel,但它似乎违反了MVVM。
有什么建议吗?
答案 0 :(得分:2)
正如我所评论的,更简单的方法可能是聚合器。
当StoryBoard
完成时,您可以通过聚合器(或甚至是对话框的特定聚合器)触发事件,并在VM中处理该事件以关闭对话框
e.g。如果您没有聚合器,则需要提供聚合器的东西(不确定您是否使用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原则的情况下逃脱
答案 1 :(得分:2)
我认为避免查看代码的最佳方法是使用Blend交互库中的StoryboardCompletedTrigger
:
首先在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>
答案 2 :(得分:0)
您可以使用Marlon Grech附加命令行为库将该事件绑定到命令。
可以从这里下载库: http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/