我想以两种方式对按钮的颜色进行动画更改(基于其
IsEnabled
属性):
我尝试将
EventTrigger
与 RoutedEvent
一起使用,但只有一个名为 Button.IsEnabledChanged
的事件。
我有一个按钮,其
IsEnabled
属性根据逻辑状态进行更改。
状态机正在工作,但我想在启用或禁用按钮时更改按钮的颜色(使用 ColorAnimation
)。
最好的方法是什么?
定义如下样式:
<Style x:Key="ButtonEnabledStyle" TargetType="Button">
<Setter Property="Background" Value="White" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false" >
<Setter Property="Background" Value="Black" />
</Trigger>
</Style.Triggers>
</Style>
然后将其分配给您的按钮,如下所示:
<Button Content="I'm a button" Style="{StaticResource ButtonEnabledStyle}" />
我希望您可以使用EventTrigger,但它们仅适用于routed事件。您将使用的事件“IsEnabledChanged”是不是路由事件,因此您不能使用EventTrigger。但是,还有另一种方法,您可以使用 VisualStateManager 并为“禁用”和“正常”状态提供自己的动画。
您可以在代码隐藏中执行动画,而不是使用 VisualStateManager,并且可能可以声明自己的自定义 RoatedEvent。我的解决方案使用 VisualStateManager,其优点是它完全在 XAML 中执行。
要使用 VisualStateManager,您将使用 ControlTemplate 创建样式,我的研究尚未发现任何其他方法。这需要您构建大部分按钮的显示功能。这是我的示例的启用和禁用状态的屏幕截图:
为了模仿正常的按钮外观,我使用了两个矩形,一个在另一个之上,作为按钮的外观。看左上方:您可以看到按钮的深灰色顶部,它来自我的一个矩形,黑色底部部分来自我的另一个矩形。右侧的禁用外观使用相同的两个矩形,但动画将颜色更改为 White 和 WhiteSmoke。我为每个矩形提供一个ColorAnimation。
这是使用 VisualStateManager 的样式:
<Window.Resources>
<Style TargetType="Button" x:Key="AnimatedStyle" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<!-- Define our button's border. Note that
the text color is inherited by child
elements, that is we give it a name, so
we can target it with the animation -->
<Border BorderBrush="Black" BorderThickness="1"
CornerRadius="2"
TextBlock.Foreground="WhiteSmoke"
Name="theBorder">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<!-- To match the appearance of a typical button,
we use two rectangles -->
<Rectangle Name="topBackground" Fill="DarkGray"/>
<Rectangle Grid.Row="1" Name="bottomBackground"
Fill="Black" />
<!-- The content presenter shows the
button's text -->
<ContentPresenter Grid.RowSpan="2"
VerticalAlignment="Center"
HorizontalAlignment="Center" />
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<!-- Here is where we define
the disable animation -->
<VisualState Name="Disabled">
<Storyboard>
<ColorAnimation
Storyboard.TargetName="topBackground"
Storyboard.TargetProperty="(Rectangle.Fill).(Color)"
To="White" Duration="0:0:.5" />
<ColorAnimation
Storyboard.TargetName="bottomBackground"
Storyboard.TargetProperty="(Rectangle.Fill).(Color)"
To="WhiteSmoke" Duration="0:0:0.5" />
<ColorAnimation
Storyboard.TargetName="theBorder"
Storyboard.TargetProperty="(TextBlock.Foreground).(Color)"
To="Gray" Duration="0:0:0.5" />
</Storyboard>
</VisualState>
<!-- Here is where the enabled animation
is defined -->
<VisualState Name="Normal">
<Storyboard>
<ColorAnimation
Storyboard.TargetName="topBackground"
Storyboard.TargetProperty="(Rectangle.Fill).Color"
To="DarkGray" Duration="0:0:0.5" />
<ColorAnimation
Storyboard.TargetName="bottomBackground"
Storyboard.TargetProperty="(Rectangle.Fill).(Color)"
To="Black" Duration="0:0:0.5" />
<ColorAnimation
Storyboard.TargetName="theBorder"
Storyboard.TargetProperty="(TextBlock.Foreground).Color"
To="WhiteSmoke" Duration="0:0:0.5" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
以下是一些使用该样式并演示动画效果的 XAML:
<Grid>
<!--The button uses the style from above. Note that we control
whether it is enabled by binding the Enabled property to the checkbox's
property 'IsChecked', that way we don't need
any code-behind -->
<Button Content="Test Button" Name="btnTest"
IsEnabled="{Binding ElementName=chkEnabled,Path=IsChecked}"
Height="30" Margin="5"
Click="btnTest_Click"
Style="{StaticResource AnimatedStyle}" />
<CheckBox Grid.Column="1" Content="Enable Button"
Name="chkEnabled" IsChecked="True" VerticalAlignment="Center" />
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
</Grid>
最后,为了证明该按钮确实被禁用/启用,这里是整个代码隐藏(除了样板代码),它是通过单击按钮触发的,但仅在启用时触发:
private void btnTest_Click(object sender, RoutedEventArgs e) {
MessageBox.Show("You clicked the button, it must be enabled.");
}