【问题标题】:Cannot animate opacity on an immutable object instance无法在不可变对象实例上设置不透明度动画
【发布时间】:2015-10-31 12:55:41
【问题描述】:

我想制作带有样式的自定义按钮。

<Grid>
<Button x:Name="btnRun" Style="{StaticResource ButtonStyle}" Content="Run"
Click="btn_Run" />
</Grid>

样式具有取决于鼠标位置的动画。动画需要改变 DropShadowEffect 的不透明度。但这不起作用。在运行时当用户将鼠标悬停在按钮程序上时抛出异常:

无法在不可变对象实例上为不透明度设置动画

这个问题有解决办法吗?

<Window.Resources>
    <DropShadowEffect x:Key="dropShadow" x:Name="dropName" Color="red"  ShadowDepth="0" BlurRadius="42" Direction="10"  />
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Effect" Value="{StaticResource dropShadow}" />
        <Setter Property="Background" Value="Red"/>
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <ControlTemplate.Resources>

                        <Storyboard x:Key="myStoryboard">
                            <DoubleAnimationUsingKeyFrames
                                                Storyboard.Target= "{StaticResource ResourceKey=dropShadow}"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0:0:1.6"
                                                RepeatBehavior="Forever">
                                <LinearDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                                <LinearDoubleKeyFrame KeyTime="0:0:0.8" Value="1"/>
                                <LinearDoubleKeyFrame KeyTime="0:0:1.6" Value="0"/>
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>                            
                    </ControlTemplate.Resources>
                    <Grid>
                        <Path Fill="{TemplateBinding Background}"
                        Data="M 241,200 
          A 20,20 0 0 0 200,240
          C 210,250 240,270 240,270
          C 240,270 260,260 280,240
          A 20,20 0 0 0 239,200" Margin="0,0,0,-15" Stretch="Fill" />
                        <ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                      HorizontalAlignment="{TemplateBinding HorizontalAlignment}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Trigger.EnterActions>
                                <BeginStoryboard Storyboard="{StaticResource myStoryboard}" />
                            </Trigger.EnterActions>
                            <Trigger Property="IsMouseOver" Value="False">                                
                        </Trigger>                            
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>            
    </Style>
</Window.Resources>

【问题讨论】:

  • 您正在为 静态资源设置动画,默认情况下该资源在所有消费者之间共享。尝试将阴影直接添加到控件模板中并为其设置动画。
  • 我尝试将 DropShadowEffect 添加到 ControlTemplate.Resources 但我仍然遇到同样的问题
  • 好的,在 Visual Studio 中启动它并让它工作,检查我在下面发布的正确答案。好心顺便说一句...没想到会这样;)

标签: .net wpf xaml


【解决方案1】:

StaticResource 不能动画,所以关键是在 ControlTemplate 中指定 DropShadowEffect,然后可以在 Storyboard/DoubleAnimationUsingKeyFrames 中引用:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>

        <Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="Background" Value="Red"/>
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <ControlTemplate.Resources>
                            <Storyboard x:Key="myStoryboard">
                                <DoubleAnimationUsingKeyFrames
                                                Storyboard.TargetName= "dropName"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0:0:1.6"
                                                RepeatBehavior="Forever">
                                    <LinearDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                                    <LinearDoubleKeyFrame KeyTime="0:0:0.8" Value="1"/>
                                    <LinearDoubleKeyFrame KeyTime="0:0:1.6" Value="0"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </ControlTemplate.Resources>
                        <Grid>
                            <Grid.Effect>
                                <DropShadowEffect x:Name="dropName" Color="red"  ShadowDepth="0" BlurRadius="42" Direction="10"  />                                        
                            </Grid.Effect>
                            <Path Fill="{TemplateBinding Background}"
                        Data="M 241,200 
          A 20,20 0 0 0 200,240
          C 210,250 240,270 240,270
          C 240,270 260,260 280,240
          A 20,20 0 0 0 239,200" Margin="0,0,0,-15" Stretch="Fill" />
                            <ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                      HorizontalAlignment="{TemplateBinding HorizontalAlignment}"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Trigger.EnterActions>
                                    <BeginStoryboard Name="BeginStoryboard" Storyboard="{StaticResource myStoryboard}" />
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <RemoveStoryboard BeginStoryboardName="BeginStoryboard" />
                                </Trigger.ExitActions>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <Button  Style="{StaticResource ButtonStyle}" Content="Run"  />
    </Grid>
</Window>

【讨论】:

  • 糟糕的答案。请解释一下问题所在以及您是如何解决的?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-24
  • 2010-09-25
  • 2012-12-22
  • 1970-01-01
相关资源
最近更新 更多