处理WPF中的Button状态

时间:2014-12-19 08:57:21

标签: wpf button state visualstatemanager

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

所有按钮都有一个带有VisualState属性的样式,因此它们都具有Normal,OnMouseOver和Pressed状态的不同样式。按下所有按钮后,在ModelView上执行命令。

我想要的是每次按下一个按钮,首先它保持按下状态直到按下另一个按钮,其次,可以从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还是代码?怎么样?

1 个答案:

答案 0 :(得分:1)

  

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

你想要的是一组RadioButton,但可能是那些看起来像普通Button的样式。以下是一些RadioButton的小例子,看起来有点像Button s:

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

请注意,我已经使用基本的Trigger添加了一些基本的状态功能...使用VisualStateManager在这里根本不需要,并且似乎会给您带来额外的问题。当我们编写需要明确单独状态的复杂VisualStateManagerUserControl时,CustomControl才真正发挥作用。出于简单的目的,您应该使用Trigger代替。

  

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

你的第二个问题的答案已被回答了很多次,之后用户界面将不会再次进入。我只想说你可以在How to bind RadioButtons to an enum?问题(或许多其他在线资源)中找到详细信息。简而言之,您需要定义enum,声明EnunmToBoolConverter以使您能够将enum数据绑定到每个bool IsChecked的{​​{1}}属性。然后,您可以从视图模型中设置要选择的每个RadioButton