WPF:在故事板动画中使用预定义的颜色,用于资源字典中的按钮样式



我正在尝试编写一个button样式,它存在于自己的资源字典中。它应该有一个基本动画,当鼠标在按钮上移动时,按钮背景从深灰色渐变为浅灰色。

问题是,它似乎不喜欢我在情节串连板中通过键特定地引用预定义颜色的事实。我不明白为什么会这样,因为我已经习惯了引用现有的资源。

运行时引发异常:

"InvalidOperationException: Cannot freeze this Storyboard timeline tree for use across threads"

以下是按钮的未完成样式:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Style.Components.Buttons">

<Style TargetType="{x:Type Button}" x:Key="LargeFlatListOptionButtonStyle">
<Setter Property="Foreground" Value="{DynamicResource TextParagraphWhiteP1}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="{DynamicResource BackgroundGreyLevel2}" />
<Setter Property="MinHeight" Value="32" />
<Setter Property="MinWidth" Value="50" />
<Setter Property="Padding" Value="6,2" />
<Setter Property="BorderBrush" Value="{DynamicResource ControlOutlineUnselected}" />
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Border Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<!-- ANIMATIONS -->
<EventTrigger RoutedEvent="Button.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation To="{DynamicResource BackgroundGreyLevel2Color}" Storyboard.TargetProperty="(Border.BorderBrush).Color" Duration="0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>

这里定义了颜色资源:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
...
<SolidColorBrush x:Key="BackgroundGreyLevel2" Color="#FF464646" />
<SolidColorBrush x:Key="TextParagraphWhiteP1" Color="White" />
<Color x:Key="BackgroundGreyLevel2Color" >#FF464646</Color>
...
</ResourceDictionary>

当然,我可以只写我希望它褪色为内联的颜色,但我更喜欢使用我已经定义的资源,就好像我们的风格从灰色更新为蓝色一样;我必须记住在这里和所有其他内联位置更改它。

引用Microsoft Docs on Storyboards。

不能使用动态资源引用或数据绑定表达式来设置情节提要或动画属性值。这是因为Style中的所有内容都必须是线程安全的,并且定时系统必须冻结Storyboard对象以使其线程安全。如果情节提要或其子时间线包含动态资源引用或数据绑定表达式,则无法冻结该情节提要。

我可以建议一些变通办法(我所看到的),这可能对你有效,也可能不适用:

  • 使用StaticResource标记扩展引用Color资源(如果您重新定义颜色资源,它会起作用,但不允许库的用户稍后重新定义它)。然后,可以为按钮创建一个"基本样式",并为不同颜色的按钮创建特定的样式(您可以基于该"基础样式"并使用StaticResource添加动画)
  • 更改ControlTemplate,使两个不同颜色的曲面重叠在一起(例如,在具有深灰色背景的"边界"的顶部有一个具有浅灰色背景的边界),然后设置顶部元素的Opacity的动画。你基本上淡出了顶部元素。这些元素可以使用DynamicResource来设置它们的属性

最新更新