在ViewModel的PropertyChanging / PropertyChanged事件上触发动画

3
在一个WPF项目中,我有一个ItemsControl绑定到ViewModel的集合。它的ItemTemplate包含一个Image控件,绑定到对象集合的属性。我有一个计时器,每分钟从JSON服务获取新的图像,并将它们分配给与Image绑定的属性。
我想做的是在该属性更改时触发一个简单的动画。特别地,我想在为我的属性分配新图像之前触发一个简单的淡出动画,这将涉及PropertyChanging事件,以及在PropertyChanged上淡入动画,这样我就可以在视图中平稳地过渡从旧图像到新图像。
我尝试了以下来自另一个问题,但那会在属性更改后触发动画,这不是我想要的:
<Image 
    x:Name="ChannelImage"
    Width="230" Height="230" 
    Source="{Binding ImageByteArray, Converter={StaticResource ByteArrayToBitmapImageConverter}, 
                                     NotifyOnTargetUpdated=True}">
    <Image.Triggers>
        <EventTrigger RoutedEvent="Binding.TargetUpdated">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation 
                        Storyboard.TargetName="ChannelImage"
                        Storyboard.TargetProperty="Opacity"
                        BeginTime="0:0:0"
                        Duration="0:0:1"
                        To="0"/>
                    <DoubleAnimation 
                        Storyboard.TargetName="ChannelImage"
                        Storyboard.TargetProperty="Opacity"
                        BeginTime="0:0:2"
                        Duration="0:0:1"
                        To="1"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Image.Triggers>
</Image>

任何帮助都将不胜感激。
1个回答

4
在您的情况下,要淡出旧图像并淡入新图像并不容易。我会按照以下步骤来保持良好的关注点分离:
  1. 从uri中获取图像,在代码中创建一个新的Image。如果您需要更多信息,请参考Stack Overflow上的这个问题
  2. 如果您想应用MVVM,则应在视图模型中执行第1步,并设置相应引发PropertyChanged的属性。否则,只需手动更新第3步中提到的相应控件即可。
  3. 实现一个自定义的ContentControl,它实际上完成了大部分工作:当其Content属性发生更改时,它会淡出旧内容并淡入新内容。这是最难的部分,但如果引入此新控件,则可以像以前一样编写视图模型,并将所有淡入淡出的内容留给这个新控件。
我为您实现了一个小项目,您可以通过这个Dropbox链接(需要.NET 4.5)下载。我创建了一个名为AnimatedContentControl的WPF自定义控件,默认控件模板内有两个内容呈现器。当在此控件上设置Content属性时,旧内容被分配给OldContent依赖项属性,并淡出。然后,新内容就会淡入。所有这些都是使用控件模板资源中的FadeInFromRight故事板完成的。此故事板在AnimatedContentControl.cs中的重写方法OnContentChanged中启动。

其他类只是使用默认MVVM模式的MainWindowMainWindowViewModel

如果您有任何问题,请随时问我。我希望我能帮您解决这个问题。


非常感谢您抽出时间创建一个示例项目,这对我来说非常有帮助。由于我的自定义控件技能不是很好,我可能想不到这样的解决方案。我会看看如何将其整合到我的项目中,并向您汇报结果。 - Pantelis
1
如果您想的话,可以将AnimatedContentControl.csIStoryboardFinder.csResourceDictionaryStoryboardFinder.csAnimatedContentControlDefaultStyle.xamlGeneric.xaml复制到您的项目中。两个xaml文件必须位于名为Themes的文件夹中。之后,您只需像在MainWindow.xaml中所做的那样绑定内容属性即可。 - feO2x
1
+1 对于自定义控件,因为它使动画可以通过简单的视图和视图模型插入来重复使用。 - Rohit Vats
这太棒了。你所做的内容相当复杂,但它工作得很好,而且你可以直接将其复制粘贴到你的项目中,它就可以工作了。我正在使用它来呈现状态文本,它确实为我的应用程序增添了额外的光彩。 - Ebsan
1
如果您正在使用此功能来展示自己的自定义控件(控件内部的控件),您可能需要增加关键时间。我不得不增加关键时间,以使更大的控件平滑地缓入和缓出。 - Ebsan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接