动画、图像、源和绑定

本文关键字:绑定 图像 动画 | 更新日期: 2023-09-27 18:25:01

我有这个视图模型:

public class ViewModel : ViewModelBase
{
    public ViewModel()
    {
        // indeed, images are dynamically generated
        normal = new BitmapImage(new Uri("Normal.jpg", UriKind.Relative));
        flash = new BitmapImage(new Uri("Flash.jpg", UriKind.Relative));
    }
    public bool IsFlashing
    {
        get { return isFlashing; }
        set
        {
            if (isFlashing != value)
            {
                isFlashing = value;
                OnPropertyChanged("IsFlashing");
            }
        }
    }
    private bool isFlashing;
    public ImageSource Normal
    {
        get { return normal; }
        private set
        {
            if (normal != value)
            {
                normal = value;
                OnPropertyChanged("Normal");
            }
        }
    }
    private ImageSource normal;
    public ImageSource Flash
    {
        get { return flash; }
        set
        {
            if (flash != value)
            {
                flash = value;
                OnPropertyChanged("Flash");
            }
        }
    }
    private ImageSource flash;
}

IsFlashing == true时,我想为视图中的图像设置动画(从NormalFlash再返回)。为了证明我正在努力实现的目标,我将发布一段XAML:

        <DataTemplate x:Key="MyTemplate">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition />
                </Grid.RowDefinitions>
                <CheckBox Content="Is flashing" IsChecked="{Binding IsFlashing}"/>
                <Image x:Name="MyImage" Grid.Row="1" Source="{Binding Normal}"/>
            </Grid>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding IsFlashing}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="MyImage" 
                                                               Storyboard.TargetProperty="Source" 
                                                               RepeatBehavior="Forever">
                                    <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding Normal}"/>
                                    <DiscreteObjectKeyFrame KeyTime="0:0:1" Value="{Binding Flash}"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>

这不起作用,因为动画引擎无法冻结带有绑定的故事板。还有其他方法可以做到这一点吗?

我可以使用视图中的计时器模型来解决这个问题。。。但这种方法很有味道。

更新根据Richard Deeming的回答,数据模板看起来是这样的。它可以工作,而且肯定比计时器更好:

        <DataTemplate x:Key="MyTemplate">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition />
                </Grid.RowDefinitions>
                <CheckBox Content="Is flashing" IsChecked="{Binding IsFlashing}"/>
                <Image x:Name="NormalImage" Grid.Row="1" Source="{Binding Normal}"/>
                <Image x:Name="FlashImage" Grid.Row="1" Source="{Binding Flash}" Visibility="Collapsed"/>
            </Grid>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding IsFlashing}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalImage" 
                                                               Storyboard.TargetProperty="Visibility" 
                                                               RepeatBehavior="Forever"
                                                               Duration="0:0:1">
                                    <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/>
                                    <DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="{x:Static Visibility.Collapsed}"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                        <BeginStoryboard>
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FlashImage" 
                                                               Storyboard.TargetProperty="Visibility" 
                                                               RepeatBehavior="Forever"
                                                               Duration="0:0:1">
                                    <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}"/>
                                    <DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="{x:Static Visibility.Visible}"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard FillBehavior="Stop">
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalImage" 
                                                               Storyboard.TargetProperty="Visibility"
                                                               Duration="0:0:1">
                                    <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                        <BeginStoryboard>
                            <Storyboard FillBehavior="Stop">
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FlashImage" 
                                                               Storyboard.TargetProperty="Visibility"
                                                               Duration="0:0:1">
                                    <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>

动画、图像、源和绑定

最简单的解决方案可能是有两个重叠的图像——一个绑定到Normal源,另一个绑定至Flash源。然后,可以使用Storyboard为两个图像上的Visibility属性设置动画。