使用 MVVM 的动态视图动画
我一直在试图弄清楚当 ViewModel 中的属性更新时如何有效地触发 View 中的动画,其中动画取决于所述属性的值。
我使用单个视图和视图模型在一个简单的应用程序中重新创建了我的问题。这里的目标是使用 ColorAnimation 来过渡矩形的颜色变化。作为参考,我一直在使用 Josh Smith 的 MVVM Foundation 包。
示例项目可以在此处下载。
总而言之,我想为颜色过渡设置动画每当 Color 属性更改时视图。
MainWindow.xaml
<Window x:Class="MVVM.ColorAnimation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ColorAnimation="clr-namespace:MVVM.ColorAnimation" Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<ColorAnimation:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Rectangle Margin="10">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding Color}"/>
</Rectangle.Fill>
</Rectangle>
<StackPanel Orientation="Horizontal" Grid.Row="1">
<Button Command="{Binding BlueCommand}" Width="100">Blue</Button>
<Button Command="{Binding GreenCommand}" Width="100">Green</Button>
</StackPanel>
</Grid>
</Window>
MainWindowViewModel.cs
namespace MVVM.ColorAnimation
{
using System.Windows.Input;
using System.Windows.Media;
using MVVM;
public class MainWindowViewModel : ObservableObject
{
private ICommand blueCommand;
private ICommand greenCommand;
public ICommand BlueCommand
{
get
{
return this.blueCommand ?? (this.blueCommand = new RelayCommand(this.TurnBlue));
}
}
private void TurnBlue()
{
this.Color = Colors.Blue;
}
public ICommand GreenCommand
{
get
{
return this.greenCommand ?? (this.greenCommand = new RelayCommand(this.TurnGreen));
}
}
private void TurnGreen()
{
this.Color = Colors.Green;
}
private Color color = Colors.Red;
public Color Color
{
get
{
return this.color;
}
set
{
this.color = value;
RaisePropertyChanged("Color");
}
}
}
}
是否有从视图触发 ColorAnimation 而不是值之间的即时转换?我目前执行此操作的方式是另一个应用程序,非常混乱,因为我通过 ViewModel 属性设置 ViewModel,然后使用 PropertyObserver 监视值更改,然后创建动画并触发它来自代码隐藏:
this.colorObserver = new PropertyObserver<Player>(value)
.RegisterHandler(n => n.Color, this.CreateColorAnimation);
在我处理许多颜色和许多潜在动画的情况下,这变得非常混乱,并且弄乱了我手动将 ViewModel 传递到 View 而不是简单地通过绑定两者的事实资源字典。我想我也可以在 DataContextChanged 事件中执行此操作,但是有更好的方法吗?
I've been trying to figure out how to effectively trigger animations in a View when a property in the ViewModel updates, where the animation depends on the value of said property.
I've recreated my problem in a simple application with a single View and ViewModel. The goal here is to transition the color change of a rectangle by using a ColorAnimation. For reference, I've been using the MVVM Foundation package by Josh Smith.
The example project can be downloaded here.
To summarize, I want to animate the color transition in the View whenever the Color property changes.
MainWindow.xaml
<Window x:Class="MVVM.ColorAnimation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ColorAnimation="clr-namespace:MVVM.ColorAnimation" Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<ColorAnimation:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Rectangle Margin="10">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding Color}"/>
</Rectangle.Fill>
</Rectangle>
<StackPanel Orientation="Horizontal" Grid.Row="1">
<Button Command="{Binding BlueCommand}" Width="100">Blue</Button>
<Button Command="{Binding GreenCommand}" Width="100">Green</Button>
</StackPanel>
</Grid>
</Window>
MainWindowViewModel.cs
namespace MVVM.ColorAnimation
{
using System.Windows.Input;
using System.Windows.Media;
using MVVM;
public class MainWindowViewModel : ObservableObject
{
private ICommand blueCommand;
private ICommand greenCommand;
public ICommand BlueCommand
{
get
{
return this.blueCommand ?? (this.blueCommand = new RelayCommand(this.TurnBlue));
}
}
private void TurnBlue()
{
this.Color = Colors.Blue;
}
public ICommand GreenCommand
{
get
{
return this.greenCommand ?? (this.greenCommand = new RelayCommand(this.TurnGreen));
}
}
private void TurnGreen()
{
this.Color = Colors.Green;
}
private Color color = Colors.Red;
public Color Color
{
get
{
return this.color;
}
set
{
this.color = value;
RaisePropertyChanged("Color");
}
}
}
}
Is there anyway from the View to trigger a ColorAnimation instead of an instant transition between the values? The way I'm currently doing this is another application is quite messy, in that I set the ViewModel through a ViewModel
property, and then using a PropertyObserver to monitor value changes, then create the Animation and trigger it from the codebehind:
this.colorObserver = new PropertyObserver<Player>(value)
.RegisterHandler(n => n.Color, this.CreateColorAnimation);
In a situation where I'm dealing with many colors and many potential animations, this becomes quite a mess, and messes up the fact that I'm manually passing in the ViewModel to the View than simply binding the two through a ResourceDictionary. I suppose I could do this in the DataContextChanged
event as well, but is there a better way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果只是为了一些动画,我建议使用视觉状态。然后您可以在视图上使用 GoToAction 行为来触发不同的动画。如果您正在处理很多类似的动画,创建自己的行为将是更好的解决方案。
更新
我创建了一个非常简单的行为来为矩形提供一点彩色动画。这是代码。
在 xaml 中,您只需像这样附加此行为,
当您单击矩形时,它应该从黑色变为红色。
If just for a few animations I would recommend using Visual States. Then you can use GoToAction behavior on the view to trigger different animations. If you are dealing with a lot of similar animations, creating your own behavior would be a better solution.
Update
I have created a very simple behaivor to give a Rectangle a little color animation. Here is the code.
In xaml, you simply attach this behavior like this,
When you click the Rectangle, it should go from Black color to Red.
我使用了 Xin 发布的代码,并做了一些非常小的周(代码如下)。唯一的 3 个实质性差异:
我创建了适用于任何 UIElement 的行为,而不仅仅是矩形
我使用了 PropertyChangedTrigger 而不是 EventTrigger。这让我可以监视 ViewModel 上的颜色属性,而不是监听单击事件。
我将 FillColor 绑定到 ViewModel 的 Color 属性。
要使用它,您需要下载 Blend 4 SDK(它是免费的,只有在您还没有 Expression Blend 时才需要它),并添加对 System.Windows.Interactivity 和 Microsoft.Expression.Interactions 的引用
。行为类的代码:
现在这是将其连接到矩形的 XAML:
这确实是 Xin 的想法 - 我只是稍微清理了一下。
I used the code that Xin posted, and made a few very minor tweeks (code is below). The only 3 material differences:
I created the behavior to work on any UIElement, not just a rectangle
I used a PropertyChangedTrigger instead of an EventTrigger. That let's me Monitor the color property on the ViewModel instead of listening for click events.
I bound the FillColor to the Color property of the ViewModel.
To use this, you will need to download the Blend 4 SDK (it's free, and you only need it if you don't already have Expression Blend), and add references to System.Windows.Interactivity, and Microsoft.Expression.Interactions
Here's the code for the behavior class:
Now here's the XAML that hooks it up to your rectangle:
It was really Xin's idea -- I just cleaned it up a bit.