【问题标题】:Handling Button states in WPF在 WPF 中处理按钮状态
【发布时间】:2014-12-19 19:10:38
【问题描述】:

我有一个 WPF 应用程序,它带有一个带有一些按钮的菜单栏,用于导航到不同的部分。

所有按钮都有一个带有 VisualState 属性的样式,所以它们都有一个 Normal、OnMouseOver 和 Pressed 状态不同的样式。所有的按钮,一旦按下,就会在 ModelView 上执行命令。

我想要的是,每次按下按钮时,首先它会保持 Pressed 状态直到按下另一个按钮,其次,可以从 ModelView 端执行的 Command 事件更改按钮状态。

代码:

<Style x:Key="MainButtonStyle" TargetType="Button">
        <Setter Property="Width" Value="120"/>
        <Setter Property="Height" Value="60"/>
        <Setter Property="Margin" Value="5"/>            
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid Background="White" x:Name="ButtonGrid">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>                                            
                                        <ColorAnimation Duration="0:0:0.3" Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="Background.Color" To="Cyan"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="Background.Color" To="DarkSalmon"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

使用样式的按钮:

<ItemsControl Margin="10" Grid.Column="1" Grid.RowSpan="2" ItemsSource="{Binding HeaderButtons}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Style="{StaticResource MainButtonStyle}" Content="{Binding content}"
                            Command="{Binding DataContext.ChangePageContainerCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                            CommandParameter="{Binding containerType}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>                
        </ItemsControl>

我认为 ModelView 不相关,因为它对 Button VisualState 没有任何作用,因为我不知道如何将引用传递给 Button 调用者(作为参数或其他东西?)。

我在其他帖子中看到人们建议使用 ToggleButton 代替 Button 并将 IsChecked 设置为 true,但我不知道应该在哪里设置该属性,我的意思是,我应该将它设置在XAML 还是代码?以及如何?

【问题讨论】:

    标签: wpf button state visualstatemanager


    【解决方案1】:

    我想要的是每次按下按钮时,首先它保持按下状态,直到按下另一个按钮

    您想要的是一组RadioButtons,但可能是样式看起来像普通Buttons 的一组。下面是一些看起来有点像Buttons 的RadioButtons 的小例子:

    <StackPanel Orientation="Horizontal">
        <StackPanel.Resources>
            <Style TargetType="{x:Type RadioButton}">
                <Setter Property="BorderBrush" Value="Blue" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type RadioButton}">
                            <Border Name="Border" CornerRadius="4" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="2" Padding="10, 5" VerticalAlignment="Top" Margin="0,0,5,0">
                                <ContentPresenter />
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter TargetName="Border" Property="Border.Background" Value="LightBlue" />
                                </Trigger>
                                <Trigger Property="IsChecked" Value="True">
                                    <Setter TargetName="Border" Property="Border.Background" Value="LightGreen" />
                                    <Setter TargetName="Border" Property="Border.BorderBrush" Value="Green" />
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </StackPanel.Resources>
        <RadioButton Content="Button 1" />
        <RadioButton Content="Button 2" />
        <RadioButton Content="Button 3" />
    </StackPanel>
    

    请注意,我已经使用基本的Triggers 添加了一些基本的状态功能......在这里使用VisualStateManager 根本没有必要,而且似乎会给您带来额外的问题。当我们编写复杂的UserControls 或CustomControls 需要明确的独立状态时,VisualStateManager 真正发挥作用。为了您的简单目的,您应该改用Triggers。

    是否可以通过 ModelView 端执行的 Command 事件更改按钮状态?

    您的第二个问题的答案已经回答了很多次,然后 UI 就不再在这里全部介绍了。只要说您可以在How to bind RadioButtons to an enum? 问题(或许多其他在线资源)中找到详细信息就足够了。简而言之,您需要定义一个enum,声明一个EnunmToBoolConverter,以使您能够将您的enum 数据绑定到每个bool IsCheckedbool IsChecked 属性RadioButton。然后,您将能够设置是否从视图模型中选择每个 Button

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-23
      • 2020-04-25
      • 1970-01-01
      • 2023-03-26
      相关资源
      最近更新 更多