WPF:在情节提要动画中使用预定义的颜色,用于资源字典中的按钮样式
WPF: Using predefined colour in storyboard animation, for a buttons style within resource dictionary
我正在尝试编写 button
style,它存在于自己的资源字典中。它应该有一个 基本动画 ,当鼠标移到它上面时,按钮背景从深灰色逐渐变为浅灰色。
问题是它似乎不喜欢我在情节提要中通过键特别引用预定义颜色这一事实。我不明白这是为什么,因为我相当习惯于引用现有资源。
运行时出现异常:
"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。
You can't use dynamic resource references or data binding expressions to set Storyboard or animation property values. That's because everything inside a Style must be thread-safe, and the timing system must freeze Storyboard objects to make them thread-safe. A Storyboard cannot be frozen if it or its child timelines contain dynamic resource references or data binding expressions.
我可以建议一些变通方法(我所看到的),它们可能对您有用,也可能不适合您:
- 使用
StaticResource
标记扩展来引用颜色资源(如果您重新定义颜色资源,它会起作用,但不允许您图书馆的用户稍后重新定义它)。然后可以为按钮设置 "base style",并为不同颜色的按钮创建特定样式(您基于 "base style" 并使用 StaticResource
添加动画)。
- 更改
ControlTemplate
使 2 个不同颜色的表面相互重叠(假设您在深灰色背景的边框之上有一个浅灰色背景的边框),然后为Opacity
的顶部元素。你基本上淡出顶部元素。这些元素可以使用 DynamicResource
来设置它们的属性。
我正在尝试编写 button
style,它存在于自己的资源字典中。它应该有一个 基本动画 ,当鼠标移到它上面时,按钮背景从深灰色逐渐变为浅灰色。
问题是它似乎不喜欢我在情节提要中通过键特别引用预定义颜色这一事实。我不明白这是为什么,因为我相当习惯于引用现有资源。
运行时出现异常:
"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。
You can't use dynamic resource references or data binding expressions to set Storyboard or animation property values. That's because everything inside a Style must be thread-safe, and the timing system must freeze Storyboard objects to make them thread-safe. A Storyboard cannot be frozen if it or its child timelines contain dynamic resource references or data binding expressions.
我可以建议一些变通方法(我所看到的),它们可能对您有用,也可能不适合您:
- 使用
StaticResource
标记扩展来引用颜色资源(如果您重新定义颜色资源,它会起作用,但不允许您图书馆的用户稍后重新定义它)。然后可以为按钮设置 "base style",并为不同颜色的按钮创建特定样式(您基于 "base style" 并使用StaticResource
添加动画)。 - 更改
ControlTemplate
使 2 个不同颜色的表面相互重叠(假设您在深灰色背景的边框之上有一个浅灰色背景的边框),然后为Opacity
的顶部元素。你基本上淡出顶部元素。这些元素可以使用DynamicResource
来设置它们的属性。