2017-11-18 328 views
0

我正在尝试编写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> 

当然,我只能写出我希望淡入淡出的颜色,但我更愿意使用我已定义的资源,就好像我们的样式从灰色更新为例如蓝色;我不得不记得在这里和所有其他内联位置更改它。

回答

1

来自Microsoft Docs on Storyboards的报价。

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

我可以建议一些解决方法(我见过做),这可能会或可能不会为你工作:

  • 使用StaticResource标记扩展引用颜色资源(它会工作,如果你重新定义颜色资源,但不会允许您的库的用户稍后重新定义它)。然后,人们可以为按钮设置“基本风格”,并为不同颜色的按钮创建特定样式(基于该“基本样式”并使用StaticResource添加动画)。
  • 更改ControlTemplate,以便您有两个不同颜色的面(彼此之上)(例如,您可以在具有深灰色背景的边框顶部具有浅灰色背景的边框),然后为顶层元素设置动画Opacity。你基本上淡出了最重要的元素。那些元素可以使用DynamicResource来设置它们的属性。
+0

djomlastic,谢谢你的帮助。我可以通过“重新定义颜色资源”来问你的第一个建议是什么意思吗? –

+0

@BenHayward好吧,如果您将BackgroundGreyLevel2Color更改为某种其他颜色(如红色),但您不更改该按键,则您的按钮将变为红色。 StaticResource vs DynamicResource的问题依然存在,所以如果你的图书馆的用户决定他希望BackgroundGreyLevel2Color是黄金(而不是灰色),那么该按钮将被动画为灰色。我相信第二种选择可能会更好,我已经在控制库中看到了。 – djomlastic

+0

@djomalstic我看到了 - 我试着简单地将故事板改为To =“{StaticResource BackgroundGreyLevel2Color}”,但这也行不通。我明白你的第二个建议是什么意思 - 这可能确实是最好的解决方法。我会放弃它!非常感谢 –