如何在XAML中完成的故事板上调用命令

时间:2015-04-12 20:08:24

标签: c# wpf xaml mvvm

我有一个按钮,它应关闭当前窗口,然后打开另一个窗口。但我想在关闭它之前首先淡出窗口。我创建了一个故事板:

<Storyboard x:Key="Storyboard1">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="Window">
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>

我有按钮:

<Button Content="Log In" Height="50" Margin="5" VerticalAlignment="Top" Width="190" DockPanel.Dock="Right" 
        Style="{DynamicResource ButtonLoginStyle}" Template="{DynamicResource ButtonBaseControlTemplate1}" 
        Command="{Binding LogInCommand}">
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.LostMouseCapture">
                    <BeginStoryboard Storyboard="{StaticResource Storyboard1}"></BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>
        </Button>

有没有办法在XAML中执行此操作?或者我应该在代码背后做什么?我试图遵循MVVM原则,所以我想将故事板引用作为参数发送到命令是不可能的。

我还有其他问题,你们使用blend for visual studio在XAML中创建UI吗?或者自己编写代码是一种更好的做法吗?

3 个答案:

答案 0 :(得分:0)

如果您正在关注MVVM模式,我建议您在代码隐藏中编写纯UI相关(故事板动画)事件,而不是引入viewmodel&amp;模型。

Model.cs - 核心业务逻辑

ViewModel.cs - 为用户视图和Dataload操作的业务逻辑

View.Xaml - UI设计和数据绑定

View.Xaml.Cs - 加载Datacontext和Pure UI相关事件(例如:故事板动画)

参考此文章:Most people are doing MVVM all wrong. Are you?

答案 1 :(得分:0)

你可以在xaml中编写这种故事板。 您需要创建一个针对您的窗口的故事板,因此您应该为您的窗口命名。 DoubleAnimation需要处理从1到0的“不透明度”,持续时间如你所愿。故事板有一个“完成”的事件,你可以关闭你的窗户等等。

<EventTrigger RoutedEvent="Button.Click" SourceName="BeginButton">
   <BeginStoryboard Name="MyBeginStoryboard">
            <Storyboard >
              <DoubleAnimation 
                Storyboard.TargetName="myWindow" 
                Storyboard.TargetProperty="Opacity" 
                Duration="0:0:5" From="1" To="0" />
            </Storyboard>
          </BeginStoryboard>
</EventTrigger>

对于你的另一个问题,混合非常适合预览复杂的样式,但只有在你编写了xaml专家之后。在我自己的观点中 - 为了更好的练习,编写自己的xaml是更好的方法

答案 2 :(得分:0)

我鼓励你去解决它。

创建具有两个依赖项属性的行为:

public class StoryboardReactionBehavior : DependencyObject, IBehavior
{
public DependencyObject AssociatedObject { get; private set; }

public void Attach(DependencyObject associatedObject)
{
    AssociatedObject = associatedObject;
    (AssociatedObject as UIElement).Tapped += StoryboardReactionBehavior_Tapped;
}

private void StoryboardReactionBehavior_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{

}

public void Detach()
{
    (AssociatedObject as UIElement).Tapped -= StoryboardReactionBehavior_Tapped;
}

}

和两个属性

public Storyboard Storyboard
    {
        get { return (Storyboard)GetValue(StoryboardProperty); }
        set { SetValue(StoryboardProperty, value); }
    }

    public static readonly DependencyProperty StoryboardProperty =
        DependencyProperty.Register("Storyboard", typeof(Storyboard), typeof(StoryboardReactionBehavior), new PropertyMetadata(null, StoryboardChanged));

    private static void StoryboardChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var behavior = d as StoryboardReactionBehavior;
        if(behavior.Storyboard !=null)
        {
            behavior.Storyboard.Completed += (s, be) =>
            {
                if (behavior.Command != null)
                {
                    behavior.Command.Execute(null);
                }
            };
        }
    }
    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof(ICommand), typeof(StoryboardReactionBehavior), new PropertyMetadata(null));

最后让我们在反应发生时调用:

private void StoryboardReactionBehavior_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
    {
        if (Storyboard != null)
        {
            Storyboard.Begin();
        }
        else if(Command != null)
        { 
          Command.Execute(null);
        }

    }

我认为这是最优雅的解决方案,可随处附着。