在出错时为按钮背景颜色添加动画效果

3

为了指示错误,我想临时更改按钮的背景颜色。我对WPF动画不熟悉,找不到一个简单的例子来继续。而且为了进一步复杂化问题,我正在使用触发器来处理错误通知。

这是我的XAML代码,我想知道如何用动画替换背景设置器(比如在五秒内闪烁三次红色等)。

<UserControl>
  <UserControl.Resources>
    <Style x:Key="ErrorStyle" TargetType="Button">
      <!--Clear the default error template (a red border)-->
      <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
          <ControlTemplate>
            <AdornedElementPlaceholder />
          </ControlTemplate>
        </Setter.Value>
      </Setter>
      <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
          <Setter Property="ToolTip" 
              Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
          <!--TODO: Replace with animation-->
          <Setter Property="Background" Value="Orange"/>
        </Trigger>
      </Style.Triggers>
    </Style>
  </UserControl.Resources>
  <Grid>
    <Button Command="{Binding ProgramCommand, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}" 
        Style="{StaticResource ErrorStyle}">
      _Program
    </Button>
  </Grid>
</UserControl>

我也愿意听取更好的(简单)错误通知建议。

3个回答

8
您可以使用Trigger.EnterActions来实现这一点。
<Trigger Property="Validation.HasError" Value="True">
    <Trigger.EnterActions>
        <BeginStoryboard>
            <Storyboard>
                <ColorAnimation Storyboard.TargetProperty="Background.Color" Duration="0:0:0.3"
                                From="White" To="Red" RepeatBehavior="3x" AutoReverse="True"/>
            </Storyboard>
        </BeginStoryboard>
    </Trigger.EnterActions>
</Trigger>

(假设背景为SolidColorBrush,因为Storyboard.TargetProperty指向其Color属性)


对于渐变,您也可以将特定的色标颜色进行动画处理,例如:

<TextBox Text="{Binding TestInt}">
    <TextBox.Background>
        <LinearGradientBrush>
            <GradientStop Color="White" Offset="0"/>
            <GradientStop Color="White" Offset="1"/>
        </LinearGradientBrush>
    </TextBox.Background>
    <TextBox.Style>
        <Style TargetType="{x:Type TextBox}">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Trigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[0].Color" Duration="0:0:0.3"
                                                From="White" To="Red" RepeatBehavior="3x" AutoReverse="True"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                </Trigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>

很好的澄清,但与@novacara的代码相同的问题是 - 如果我不指定Storyboard.Target,它将无法工作,而我不知道如何在Style内正确地执行该操作。 - Pat
什么目标?您不需要任何目标,或者您想要为哪个背景添加动画效果? - H.B.
这是绑定错误:System.Windows.Data Error: 40 : BindingExpression path error: 'Color' property not found on 'object' ''LinearGradientBrush' (HashCode=24852100)'. null可能是因为我正在绑定到一个按钮? - Pat
请检查我的第二个示例。或者使用SolidColorBrush显式覆盖按钮的默认背景(这是一个复杂的渐变)。 - H.B.
如果TargetProperty是Button.Background,这会有任何区别吗? - novacara
显示剩余3条评论

3

感谢@H.B.的回答,这是我的最终代码。您会注意到,我没有将按钮的背景设置为SolidColor,而是在默认按钮刷子的每个渐变中强行插入了颜色变化。这创建了一个效果,使整个按钮变成红色,但允许它恢复到其正常的渐变外观。

<UserControl>
  <UserControl.Resources>
    <Style Key="ErrorStyle" TargetType="Button">
      <!--Clear the default error template (a red border)-->
      <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
          <ControlTemplate>
            <AdornedElementPlaceholder />
          </ControlTemplate>
        </Setter.Value>
      </Setter>
      <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
          <Setter Property="ToolTip"
              Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
          <Trigger.EnterActions>
            <BeginStoryboard>
              <Storyboard>
                <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[0].Color" To="Red" Duration="0:0:0.5" AutoReverse="True" RepeatBehavior="3x" />
                <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[1].Color" To="Red" Duration="0:0:0.5" AutoReverse="True" RepeatBehavior="3x" />
                <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[2].Color" To="Red" Duration="0:0:0.5" AutoReverse="True" RepeatBehavior="3x" />
                <ColorAnimation Storyboard.TargetProperty="Background.GradientStops[3].Color" To="Red" Duration="0:0:0.5" AutoReverse="True" RepeatBehavior="3x" />
              </Storyboard>
            </BeginStoryboard>
          </Trigger.EnterActions>
        </Trigger>
      </Style.Triggers>
    </Style>
  </UserControl.Resources>
  <Grid>
    <Button Command="{Binding ProgramCommand, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}"
        Style="{StaticResource ErrorStyle}">
      _Program
    </Button>
  </Grid>
</UserControl>

0
<Trigger Property="Validation.HasError" Value="True">
   <BeginStoryboard>
      <Storyboard>
         <ColorAnimation Storyboard.TargetProperty="Background" From="White" 
            To="Red" Duration="0:0:1" AutoReverse="True" RepeatBehavior="3x"/>
      </Storyboard>
   </BeginStoryboard>
</Trigger>

我已经接近成功了,但似乎需要指定Storyboard.Target,否则目标将是一个LinearGradientBrush。我想将其设置为RelativeResource TemplatedParent,但此控件上没有模板(即如果我包括Background.Color setter,则TemplatedParent有效;如果不包括,则无效)。而且我不能在样式中使用Storyboard.TargetName(根据编译器)。 - Pat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接