在按钮单击时运行两个命令和动画

本文关键字:两个 命令 动画 单击 按钮 运行 | 更新日期: 2023-09-27 18:36:56

在我的应用程序中,我有一个Left Grid和一个Right Grid。最初,Left Grid完全展开(GridLength = 7*),而Right Grid不可见(Width = 0*)。

如果单击LeftGrid中的Button并且未展开Right Grid,则Right Grid应展开为3* Width

如果展开Right Grid并连续单击两次LeftGrid中的Button,则RightGrid应收缩回Width 0*

这些扩张/收缩应该是Animated的。

单击Button时,必须发生三件事。

1)所选Buttonid应存储在ViewModelProperty中。

2)将设置RightGridWidth存储在ViewModelProperty中。此Command处理两个连续的单击案例。

3)最后,Animation应该运行。

我遇到了一些问题:

1) 如何将两个Commands绑定到一个Button

<Button DockPanel.Dock="Top"                        
   Command="{Binding DataContext.SetSelectedItemCommand, 
             RelativeSource={RelativeSource 
             AncestorType={x:Type ItemsControl}}}"
             CommandParameter="{Binding id}"
             Command="{Binding ElementName=root, Path=DataContext.ChangeRightGridWidthCommand}"          
>

这是不允许的。

我一直在看这篇文章(http://www.codeproject.com/Articles/25808/Aggregating-WPF-Commands-with-CommandGroup)。

但是,我

不确定这是否对我有用,因为我正在定义我的ViewModel Commands

2)我正在使用自定义GridLength动画类,因为我需要在Widths中使用*

public class GridLengthAnimation : AnimationTimeline
{
    public static readonly DependencyProperty ToProperty =
    DependencyProperty.Register(
        "To", typeof(GridLength), typeof(GridLengthAnimation));
    public GridLength To
    {
        get { return (GridLength)GetValue(ToProperty); }
        set { SetValue(ToProperty, value); }
    }
    public override Type TargetPropertyType
    {
        get { return typeof(GridLength); }
    }
    protected override Freezable CreateInstanceCore()
    {
        return new GridLengthAnimation();
    }
    public override object GetCurrentValue(
        object defaultOriginValue, object defaultDestinationValue,
        AnimationClock animationClock)
    {
         return new GridLength(To.Value,
            GridUnitType.Star);
    }
}

我打算在我的XAML中使用这样的东西:

<proj:GridLengthAnimation
          Storyboard.TargetName="rightGrid"
          Storyboard.TargetProperty="Width"
          To="RightGridWidth" Duration="0:0:2" />
<Grid.ColumnDefinitions>
      <ColumnDefinition Name="leftGrid"  Width="7*"/>
      <ColumnDefinition Name="rightGrid" Width="{Binding RightGridWidth}"/>
 </Grid.ColumnDefinitions>

我应该把上面的XAML代码放在里面吗:

  <EventTrigger RoutedEvent="Button.Click">

如果是这样,我的CommandsEventTrigger会先运行吗?我需要先运行我的Commands,因为只有这样才能在Storyboard运行时正确设置To值。

我对如何将所有这些放在一起感到非常困惑。

任何帮助/建议将不胜感激!!

在按钮单击时运行两个命令和动画

快速而肮脏地使用您已有的内容,即运行动画的事件触发器。

RightGridWidth属性(带有更改通知)添加到视图模型:

public GridLength RightGridWidth
{
    get { return rightGridWidth; }
    set
    {
        rightGridWidth = value;
        OnPropertyChanged("RightGridWidth");
    }
}

SetSelectedItemCommand的执行处理程序中切换属性值:

if (RightGridWidth.Value == 0d)
{
    RightGridWidth = new GridLength(3d, GridUnitType.Star);
}
else
{
    RightGridWidth = new GridLength(0d, GridUnitType.Star);
}

Click事件触发器中运行动画:

<Button Content="Click" Command="{Binding SetSelectedItemCommand}">
    <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
            <BeginStoryboard>
                <Storyboard>
                    <local:GridLengthAnimation
                        Storyboard.Target="{Binding ElementName=col2}"
                        Storyboard.TargetProperty="Width"
                        Duration="0:0:1" To="{Binding RightGridWidth}"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Button.Triggers>
</Button>

最后,使用动画GetCurrentValue的工作实现,它必须返回一个依赖于CurrentProgress的值:

public override object GetCurrentValue(
    object defaultOriginValue, object defaultDestinationValue,
    AnimationClock animationClock)
{
    var from = (GridLength)defaultOriginValue;
    if (from.GridUnitType != To.GridUnitType ||
        !animationClock.CurrentProgress.HasValue)
    {
        return from;
    }
    var p = animationClock.CurrentProgress.Value;
    return new GridLength(
        (1d - p) * from.Value + p * To.Value,
        from.GridUnitType);
}

一种完全不同的,也许更好的方法是使用视觉状态。请参阅可视化状态管理器。