You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中实现Rectangle.Fill的ImageSource切换淡入淡出动画

实现图片切换时的淡入淡出动画方案

这里提供两种实用的WPF实现思路,基于你现有代码改造即可:

方案一:双Image叠加+绑定更新触发动画

核心思路是通过两个重叠的Image控件,切换它们的透明度实现淡入淡出效果,用绑定更新事件触发动画。

修改后的XAML代码:

<Rectangle RadiusX="1" 
           RadiusY="1"
           Width="20"
           Height="20"  
           Stroke="Black"
           StrokeThickness="0.1"                   
           Stretch="Uniform">
    <Rectangle.Fill>
        <VisualBrush>
            <VisualBrush.Visual>
                <Grid Width="{Binding RelativeSource={RelativeSource AncestorType=Rectangle}, Path=Width}"
                      Height="{Binding RelativeSource={RelativeSource AncestorType=Rectangle}, Path=Height}">
                    <!-- 显示旧图片的容器 -->
                    <Image x:Name="OldImage" Stretch="Uniform" Opacity="1">
                        <Image.Source>
                            <Binding Path="ImageSource" Mode="OneWay" NotifyOnTargetUpdated="True"/>
                        </Image.Source>
                    </Image>
                    <!-- 显示新图片的容器,初始透明 -->
                    <Image x:Name="NewImage" Stretch="Uniform" Opacity="0">
                        <Image.Source>
                            <Binding Path="ImageSource" Mode="OneWay" NotifyOnTargetUpdated="True"/>
                        </Image.Source>
                    </Image>
                </Grid>
            </VisualBrush.Visual>
        </VisualBrush>
    </Rectangle.Fill>
    <Rectangle.Triggers>
        <!-- 绑定目标更新时触发动画 -->
        <EventTrigger RoutedEvent="Binding.TargetUpdated">
            <BeginStoryboard>
                <Storyboard>
                    <!-- 旧图片淡出 -->
                    <DoubleAnimation Storyboard.TargetName="OldImage"
                                     Storyboard.TargetProperty="Opacity"
                                     From="1" To="0" Duration="0:0:0.3"/>
                    <!-- 新图片淡入 -->
                    <DoubleAnimation Storyboard.TargetName="NewImage"
                                     Storyboard.TargetProperty="Opacity"
                                     From="0" To="1" Duration="0:0:0.3"/>
                    <!-- 动画结束后同步旧图片源,避免重复加载 -->
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OldImage"
                                                  Storyboard.TargetProperty="Source">
                        <DiscreteObjectKeyFrame KeyTime="0:0:0.3" Value="{Binding ImageSource}"/>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Rectangle.Triggers>
</Rectangle>

关键注意点:绑定必须添加NotifyOnTargetUpdated="True",否则无法触发动画事件。

方案二:VisualStateManager状态切换

通过ViewModel新增状态属性,配合VisualState管理淡入淡出逻辑,结构更清晰。

1. ViewModel新增状态属性(需实现INotifyPropertyChanged)

private ImageSource _imageSource;
public ImageSource ImageSource
{
    get => _imageSource;
    set
    {
        IsImageChanging = true;
        // 延迟设置新图片,给淡出动画留执行时间
        Task.Delay(300).ContinueWith(_ =>
        {
            _imageSource = value;
            OnPropertyChanged(nameof(ImageSource));
            IsImageChanging = false;
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }
}

private bool _isImageChanging;
public bool IsImageChanging
{
    get => _isImageChanging;
    set
    {
        _isImageChanging = value;
        OnPropertyChanged(nameof(IsImageChanging));
    }
}

2. 修改View的XAML代码

<Rectangle RadiusX="1" 
           RadiusY="1"
           Width="20"
           Height="20"  
           Stroke="Black"
           StrokeThickness="0.1"                   
           Stretch="Uniform">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup Name="ImageStates">
            <VisualState Name="Normal">
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3"/>
                </Storyboard>
            </VisualState>
            <VisualState Name="Changing">
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.3"/>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Rectangle.Style>
        <Style TargetType="Rectangle">
            <Setter Property="Fill">
                <Setter.Value>
                    <ImageBrush ImageSource="{Binding ImageSource}"/>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsImageChanging}" Value="True">
                    <Setter Property="VisualStateManager.VisualStateName" Value="Changing"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding IsImageChanging}" Value="False">
                    <Setter Property="VisualStateManager.VisualStateName" Value="Normal"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Rectangle.Style>
</Rectangle>

通用注意事项

  • 动画时长(Duration="0:0:0.3")可根据需求调整,单位是时:分:秒。
  • 必须确保ViewModel的所有绑定属性正确实现INotifyPropertyChanged接口,否则绑定和动画触发都会失效。

内容的提问来源于stack exchange,提问作者AndyS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:37:20