我正在尝试制作一个Button
,该面板使用该面板的Height
属性上的动画来打开/关闭某些面板。
方法是将动画的“ To”值绑定到viewmodel属性,该属性在按钮的命令中进行了更改。
我想它应该像这样工作:
Button
被点击TargetHeight
设置为0;如果为False,则vm将其设置为True,将TargetHeight
设置为128 但是实际上它是这样工作的:
Button
被点击Height
更改为先前设置的值因此,viewmodel不会为当前单击按钮设置目标高度,而是为将来的下一次设置目标高度。
我应该做些什么才能使其正确?
不幸的是,已经尝试设置BeginTime
属性来延迟动画播放,但这没有帮助。
代码如下:
XAML
<Button Command="{Binding SwitchBottomPanel}">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BottomPanel"
Storyboard.TargetProperty="Height"
To="{Binding TargetHeight}"
Duration="0:0:0.3"
BeginTime="0:0:0.3"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
Viewmodel类:
class MainViewModel : ViewModelBase
{
private double _targetHeight;
private bool _isBottomOpened;
private double _bottomHeightBig = 128;
public double TargetHeight
{
get { return _targetHeight; }
set
{
_targetHeight = value;
RaisePropertyChanged(nameof(TargetHeight));
}
}
public bool IsBottomOpened
{
get { return _isBottomOpened; }
set
{
_isBottomOpened = value;
if (value == true) TargetHeight = _bottomHeightBig;
else TargetHeight = 0;
RaisePropertyChanged(nameof(IsBottomOpened));
}
}
public ICommand SwitchBottomPanel { get; set; }
public MainViewModel()
{
SwitchBottomPanel = new DelegateCommand(() => IsBottomOpened = !IsBottomOpened);
RaisePropertyChanged(nameof(SwitchBottomPanel));
IsBottomOpened = false;
}
}
答案 0 :(得分:1)
您可以处理视图模型的PropertyChanged
事件,并在视图中以编程方式启动动画:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
Loaded += OnLoaded;
Unloaded += OnUnloaded;
}
private MainViewModel ViewModel => DataContext as MainViewModel;
private void OnLoaded(object sender, RoutedEventArgs e) =>
ViewModel.PropertyChanged += ViewModel_PropertyChanged;
private void OnUnloaded(object sender, RoutedEventArgs e) =>
ViewModel.PropertyChanged += ViewModel_PropertyChanged;
private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) =>
BottomPanel.BeginAnimation(HeightProperty, new DoubleAnimation()
{
To = ViewModel.TargetHeight,
Duration = TimeSpan.FromSeconds(0.3)
});
}
仅仅因为您可以在纯XAML中实现诸如动画之类的功能,但这并不意味着您总是应该如此。在这个示例中,使用诸如C#这样的表达性编程语言而不是使用诸如XAML这样的标记语言来实现视图逻辑是非常有意义的。
您可能还需要考虑在视图中指定实际高度,并绑定到IsBottomOpened
属性:
<Grid x:Name="BottomPanel" Background="Yellow" Height="0" Width="200">
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding IsBottomOpened}">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Height"
To="128"
Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
如果这样做,也可以将Button
元素替换为ToggleButton
并绑定到其IsChecked
属性,而不是使用IsBottomOpened
源属性。在视图模型中是否真正需要这些属性取决于您的要求。