WPF 按钮 EventTrigger=Button.IsEnabledChanged

问题描述 投票:0回答:2

我想以两种方式对按钮的颜色进行动画更改(基于其

IsEnabled
属性):

  1. 当它从启用更改为禁用时 -> 颜色将从白色更改为黑色。
  2. 当它从禁用更改为启用时 -> 颜色将从黑色更改为白色。

我尝试将

EventTrigger
RoutedEvent
一起使用,但只有一个名为
Button.IsEnabledChanged
的事件。

我有一个按钮,其

IsEnabled
属性根据逻辑状态进行更改。 状态机正在工作,但我想在启用或禁用按钮时更改按钮的颜色(使用
ColorAnimation
)。

最好的方法是什么?

wpf button eventtrigger routed-events coloranimation
2个回答
0
投票

定义如下样式:

<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}" />

0
投票

我希望您可以使用EventTrigger,但它们仅适用于routed事件。您将使用的事件“IsEnabledChanged”是不是路由事件,因此您不能使用EventTrigger。但是,还有另一种方法,您可以使用 VisualStateManager 并为“禁用”和“正常”状态提供自己的动画。

您可以在代码隐藏中执行动画,而不是使用 VisualStateManager,并且可能可以声明自己的自定义 RoatedEvent。我的解决方案使用 VisualStateManager,其优点是它完全在 XAML 中执行。

要使用 VisualStateManager,您将使用 ControlTemplate 创建样式,我的研究尚未发现任何其他方法。这需要您构建大部分按钮的显示功能。这是我的示例的启用和禁用状态的屏幕截图:

ScreenShot.jpg![Screenshot showing the enabled and disabled states

为了模仿正常的按钮外观,我使用了两个矩形,一个在另一个之上,作为按钮的外观。看左上方:您可以看到按钮的深灰色顶部,它来自我的一个矩形,黑色底部部分来自我的另一个矩形。右侧的禁用外观使用相同的两个矩形,但动画将颜色更改为 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.");
    }
© www.soinside.com 2019 - 2024. All rights reserved.