WPF控件:如何在动画中引用资源?

时间:2010-12-02 14:09:41

标签: wpf wpf-controls styles storyboard

我编写了一个控件并成功创建了一个故事板,以便在触发事件期间生成动画。它会在一段时间内更改椭圆的填充。每次我需要更改填充时,我没有编写新的RadialGradientBrush,而是在资源中提供了两个。

修改: 我有一个Ellipse,它是控件的主要组件,受动画的影响。它的实现很简单,看起来像这样:

<Ellipse Name="myEllipse" Style="{StaticResource DimStyle}" />

当我将它添加到故事板时(而不是将画笔作为资源引用),我的动画按预期工作。当我将画笔作为资源引用时,我得到了这个例外:

"Cannot find resource named 'IlluminatedStyle'. Resource names are case sensitive."

故事板内部,这是当前引用的地方:

<UserControl.Resources>
    <Storyboard x:Key="Foo">
        <ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames.KeyFrames>
                <DiscreteObjectKeyFrame KeyTime="0:0:0.01" Value="{StaticResource IlluminatedStyle}" />
                <DiscreteObjectKeyFrame KeyTime="0:0:0.85" Value="{StaticResource DimStyle}" />
            </ObjectAnimationUsingKeyFrames.KeyFrames>
        </ObjectAnimationUsingKeyFrames>
     </Storyboard>
</UserControl.Resources>

样式非常相似,只有GradientStop颜色属性不同,所以我只为一个例子提供一种样式。

参考样式

<UserControl.Resources>
    <Style x:Key="IlluminatedStyle" TargetType="Ellipse">
        <Setter Property="Fill">
            <Setter.Value>
                <RadialGradientBrush>
                    <GradientStop Color="#FF215416" Offset="1"/>
                    <GradientStop Color="#FE38DA2E" Offset="0"/>
                    <GradientStop Color="#FE81FF79" Offset="0.688"/>
                </RadialGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>

那么如何在我的Storyboard中正确引用这样的风格?

注意StoryboardStyle都包含在同一个UserControl.Resources标记中,但在此示例中已标注。

修改
我将Style放在Storyboard UserControl.Resources之前,现在我得到一个例外说明:

  "This Freezable cannot be frozen.
   at System.Windows.Freezable.Freeze()
   at System.Windows.Freezable.GetCurrentValueAsFrozen()
   at System.Windows.Media.Animation.TimelineCollection.GetCurrentValueAsFrozenCore(Freezable source)
   at System.Windows.Freezable.CloneCoreCommon(Freezable sourceFreezable, Boolean useCurrentValue, Boolean cloneFrozenValues)
   at System.Windows.Media.Animation.Timeline.GetCurrentValueAsFrozenCore(Freezable sourceFreezable)
   at System.Windows.Freezable.GetCurrentValueAsFrozen()
   at System.Windows.Media.Animation.Clock..ctor(Timeline timeline)
   at System.Windows.Media.Animation.TimelineGroup.AllocateClock()
   at System.Windows.Media.Animation.Clock.AllocateClock(Timeline timeline, Boolean hasControllableRoot)"

2 个答案:

答案 0 :(得分:3)

Freezable无法冻结的原因有三个:

  • 它具有动画或数据绑定属性。
  • 它具有由动态资源设置的属性。
  • 它包含无法冻结的Freezable子对象。

因此,首先要找出导致问题的Freezable,然后检查以上内容。

答案 1 :(得分:1)

看到我是WPF和XAML的新手,我错误地将我的资源变成了一种风格,并没有意识到我可以简单地将画笔作为资源并完全避免使用样式。

我将对DiscreteObjectKeyFrame s'值的引用保持为新刷子资源的静态值。我将Ellipse更改为:

<Ellipse Name="myEllipse" Fill="{StaticResource DimBrush" />

删除了style属性,我直接将画笔分配给fill属性。在ObjectAnimationUsingKeyFrames标记中,我添加了Fill作为Storyboard.TargetProperty,因为我不再使用样式来装扮填充。 DiscreteObjectKeyFrame现在看起来像这样:

<DiscreteObjectKeyFrame KeyTime="0:0:0.01" Value="{StaticResource IlluminatedBrush}" />
<DiscreteObjectKeyFrame KeyTime="0:0:0.85" Value="{StaticResource DimBrush}" />

我的资源更简单,没有风格和IMO,更优雅。在我的最终解决方案中,画笔也是在动画之前定义的。

<UserControl.Resources>
    <RadialGradientBrush x:Key="DimBrush" >
        <GradientStop Color="#FF21471A" Offset="1"/>
        <GradientStop Color="#FF33802F" Offset="0"/>
        <GradientStop Color="#FF35932F" Offset="0.688"/>
    </RadialGradientBrush>
    <RadialGradientBrush x:Key="IlluminatedBrush">
        <GradientStop Color="#FF215416" Offset="1"/>
        <GradientStop Color="#FE38DA2E" Offset="0"/>
        <GradientStop Color="#FE81FF79" Offset="0.688"/>
    </RadialGradientBrush>
    <!-- Storyboard code follows... -->
</UserControl.Resources>

现在一切都按预期工作了。我可以做的最好的假设是样式不是freezable,因为它们是我删除的组件,并且我不再收到关于不能冻结的freezable的例外。