简体   繁体   English

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

[英]InvalidOperationException when trying to animate background color of a styled button in WPF

I'm trying to programmatically trigger a color animation on a button, but getting a System.InvalidOperationException when I do. 我正在尝试以编程方式触发按钮上的彩色动画,但是当我这样做时却遇到了System.InvalidOperationException It seems it can't resolve the TargetProperty because I've styled the button using a template/content presenter. 似乎无法解析TargetProperty因为我已经使用模板/内容演示者设置了按钮的样式。

The reason I style <Button> this way is to force the style to be consistent (and avoid the default blue hover effect). 我使用<Button>样式的原因是强制样式保持一致(并避免使用默认的蓝色悬停效果)。 I also have a DataTrigger that animates the background color of this button whenever it's shown (ie made Visible). 我也有一个DataTrigger,可以在显示该按钮时将其背景颜色设置为动画(即使其可见)。 Here's the full <Style> definition: 这是完整的<Style>定义:

<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>

But I also want to be able to trigger a different animation on this same button, from code. 但我也希望能够通过代码在同一按钮上触发不同的动画。 So I have a separate <Storyboard> defined elsewhere (outside the Style definition), which I trigger using TryFindResource() ... Begin() . 因此,我在其他地方(在样式定义之外)定义了一个单独的<Storyboard> ,我可以使用TryFindResource() ... Begin()触发该TryFindResource() However, because the button is using a Template, I'm having trouble getting the Background color property to properly resolve in my XAML (below). 但是,由于该按钮使用的是模板,因此我无法在我的XAML中正确获取Background color属性(如下所示)。

<Storyboard x:Key="StatusGood" Completed="AnimationStatusGood_Completed">
  <ColorAnimationUsingKeyFrames Storyboard.TargetName="PopUnderMessage" Storyboard.TargetProperty="(Border).(Background).(SolidColorBrush.Color)">
      <LinearColorKeyFrame Value="LightGreen" KeyTime="0:0:0" />
      <LinearColorKeyFrame Value="White" KeyTime="0:0:1" />
  </ColorAnimationUsingKeyFrames>
</Storyboard>

I've tried a couple of different values for the Storyboard.TargetProperty attribute here: 我在这里为Storyboard.TargetProperty属性尝试了几个不同的值:

  • (Background).(SolidColorBrush.Color) (背景)。(SolidColorBrush.Color)
  • (Border).(Background).(SolidColorBrush.Color) (边境)。(背景)。(SolidColorBrush.Color)
  • (Border.Background).(SolidColorBrush.Color) (Border.Background)。(SolidColorBrush.Color)

But all of them yield different variations on the same exception. 但是它们都在相同的异常上产生不同的变化。 I confess I'm kind of throwing darts on a board blindly as my knowledge of XAML templates and property paths is lacking. 我承认由于缺乏对XAML模板和属性路径的了解,我有点盲目地将飞镖扔在板上。 How can I get this to work? 我该如何工作?

Try this, omitting Storyboard.TargetName entirely, and omitting Border from Storyboard.TargetProperty : 尝试执行此操作,完全省略Storyboard.TargetName ,并从Storyboard.TargetProperty省略Border

<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>

Give the styled button a name: 为样式按钮命名:

<Button
    x:Name="button"
    Content="Hello, world!"
    Style="{StaticResource PopUnder}" Click="ButtonBase_OnClick" />

To activate the storyboard: 要激活情节提要:

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    Storyboard storyboard = (Storyboard)this.TryFindResource("StatusGood");
    Border border = FindVisualChild<Border>(button, "Border");
    storyboard.Begin(border);
}

For reference, the FindVisualChild helper function: 作为参考, FindVisualChild帮助函数:

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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM