WPF:在故事板动画中使用预定义颜色,用于资源字典中的按钮样式
问题描述:
我正在尝试编写button
样式,它存在于其自己的资源字典中。它应该有一个基本动画,其中当鼠标移过它时,按钮背景从深灰色变为浅灰色。WPF:在故事板动画中使用预定义颜色,用于资源字典中的按钮样式
的问题是,它似乎不喜欢,我引用故事板具体内键预定颜色的事实。我不明白为什么这是因为我习惯于引用现有资源。
将引发异常在运行时:
"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的报价。
您不能使用动态资源引用或数据绑定表达式来设置Storyboard或动画属性值。这是因为Style内的所有内容都必须是线程安全的,并且时序系统必须冻结Storyboard对象以使它们成为线程安全的。如果Storyboard或其子时间轴包含动态资源引用或数据绑定表达式,则Storyboard不能被冻结。
我可以建议一些解决方法(我见过做),这可能会或可能不会为你工作:
- 使用
StaticResource
标记扩展引用颜色资源(它会工作,如果你重新定义颜色资源,但不会允许您的库的用户稍后重新定义它)。然后,人们可以为按钮设置“基本风格”,并为不同颜色的按钮创建特定样式(基于该“基本样式”并使用StaticResource
添加动画)。 - 更改
ControlTemplate
,以便您有两个不同颜色的面(彼此之上)(例如,您可以在具有深灰色背景的边框顶部具有浅灰色背景的边框),然后为顶层元素设置动画Opacity
。你基本上淡出了最重要的元素。那些元素可以使用DynamicResource
来设置它们的属性。
djomlastic,谢谢你的帮助。我可以通过“重新定义颜色资源”来问你的第一个建议是什么意思吗? –
@BenHayward好吧,如果您将BackgroundGreyLevel2Color更改为某种其他颜色(如红色),但您不更改该按键,则您的按钮将变为红色。 StaticResource vs DynamicResource的问题依然存在,所以如果你的图书馆的用户决定他希望BackgroundGreyLevel2Color是黄金(而不是灰色),那么该按钮将被动画为灰色。我相信第二种选择可能会更好,我已经在控制库中看到了。 – djomlastic
@djomalstic我看到了 - 我试着简单地将故事板改为To =“{StaticResource BackgroundGreyLevel2Color}”,但这也行不通。我明白你的第二个建议是什么意思 - 这可能确实是最好的解决方法。我会放弃它!非常感谢 –