在按钮单击时运行两个命令和动画
本文关键字:两个 命令 动画 单击 按钮 运行 | 更新日期: 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)所选Button
的id
应存储在ViewModel
的Property
中。
2)将设置RightGrid
的Width
存储在ViewModel
的Property
中。此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">
如果是这样,我的Commands
或EventTrigger
会先运行吗?我需要先运行我的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);
}
一种完全不同的,也许更好的方法是使用视觉状态。请参阅可视化状态管理器。