C# 尝试在WPF中设置样式按钮的背景色动画时出现InvalidOperationException

C# 尝试在WPF中设置样式按钮的背景色动画时出现InvalidOperationException,c#,wpf,xaml,C#,Wpf,Xaml,我试图以编程方式触发按钮上的彩色动画,但当我这样做时,会得到一个System.invalidoOperationException。它似乎无法解析TargetProperty,因为我已经使用模板/内容演示器设置了按钮的样式 我采用这种方式设置样式的原因是为了强制样式保持一致(并避免默认的蓝色悬停效果)。我还有一个DataTrigger,每当显示该按钮(即使其可见)时,它都会为该按钮的背景色设置动画。以下是完整的定义: <Style x:Key="PopUnder" TargetType="

我试图以编程方式触发按钮上的彩色动画,但当我这样做时,会得到一个
System.invalidoOperationException
。它似乎无法解析
TargetProperty
,因为我已经使用模板/内容演示器设置了按钮的样式

我采用这种方式设置样式的原因是为了强制样式保持一致(并避免默认的蓝色悬停效果)。我还有一个DataTrigger,每当显示该按钮(即使其可见)时,它都会为该按钮的背景色设置动画。以下是完整的
定义:

<Style x:Key="PopUnder" TargetType="Button">
  <Setter Property="Foreground" Value="Black" />
  <Setter Property="FontSize" Value="34" />
  <Setter Property="FontWeight" Value="SemiBold" />
  <Setter Property="OverridesDefaultStyle" Value="True" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Border Name="Border" Background="White" BorderBrush="Red" BorderThickness="0,1,0,1">
          <TextBlock TextWrapping="Wrap" TextAlignment="Center" VerticalAlignment="Center" LineStackingStrategy="BlockLineHeight" LineHeight="40" Text="{TemplateBinding Content}" />
        </Border>
        <ControlTemplate.Triggers>
          <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Visibility}" Value="Visible">
            <DataTrigger.EnterActions>
              <BeginStoryboard>
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" RepeatBehavior="Forever">
                    <LinearColorKeyFrame Value="White" KeyTime="0:0:0" />
                    <LinearColorKeyFrame Value="LightCoral" KeyTime="0:0:1" />
                    <LinearColorKeyFrame Value="White" KeyTime="0:0:2" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </BeginStoryboard>
            </DataTrigger.EnterActions>
          </DataTrigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
我在这里为
故事板.TargetProperty
属性尝试了几个不同的值:

  • (背景)。(SolidColorBrush.Color)
  • (边框)。(背景)。(SolidColorBrush.Color)
  • (边框。背景)。(SolidColorBrush.Color)

但在同一例外情况下,它们都会产生不同的变化。我承认我有点盲目地在黑板上扔飞镖,因为我缺乏对XAML模板和属性路径的了解。我如何才能让它工作?

试试这个,完全省略
情节提要。TargetName
,并从
情节提要中省略
边框。TargetProperty

<Storyboard x:Key="StatusGood" Completed="AnimationStatusGood_Completed">
    <ColorAnimationUsingKeyFrames
        Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
        <LinearColorKeyFrame Value="LightGreen" KeyTime="0:0:0" />
        <LinearColorKeyFrame Value="White" KeyTime="0:0:1" />
    </ColorAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="StatusGood" Completed="AnimationStatusGood_Completed">
    <ColorAnimationUsingKeyFrames
        Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
        <LinearColorKeyFrame Value="LightGreen" KeyTime="0:0:0" />
        <LinearColorKeyFrame Value="White" KeyTime="0:0:1" />
    </ColorAnimationUsingKeyFrames>
</Storyboard>
<Button
    x:Name="button"
    Content="Hello, world!"
    Style="{StaticResource PopUnder}" Click="ButtonBase_OnClick" />
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    Storyboard storyboard = (Storyboard)this.TryFindResource("StatusGood");
    Border border = FindVisualChild<Border>(button, "Border");
    storyboard.Begin(border);
}
private static T FindVisualChild<T>(
    DependencyObject parent,
    string name = null)
    where T : DependencyObject
{
    if (parent != null)
    {
        int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < childrenCount; i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(parent, i);
            T candidate = child as T;
            if (candidate != null)
            {
                if (name == null)
                {
                    return candidate;
                }

                FrameworkElement element = candidate as FrameworkElement;
                if (name == element?.Name)
                {
                    return candidate;
                }
            }

            T childOfChild = FindVisualChild<T>(child, name);
            if (childOfChild != null)
            {
                return childOfChild;
            }
        }
    }

    return default(T);
}