我有一个带有菜单栏的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还是代码?怎么样?
答案 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
在这里根本不需要,并且似乎会给您带来额外的问题。当我们编写需要明确单独状态的复杂VisualStateManager
或UserControl
时,CustomControl
才真正发挥作用。出于简单的目的,您应该使用Trigger
代替。
是否可以从ModelView端执行的Command事件更改按钮状态?
你的第二个问题的答案已被回答了很多次,之后用户界面将不会再次进入。我只想说你可以在How to bind RadioButtons to an enum?问题(或许多其他在线资源)中找到详细信息。简而言之,您需要定义enum
,声明EnunmToBoolConverter
以使您能够将enum
数据绑定到每个bool IsChecked
的{{1}}属性。然后,您可以从视图模型中设置要选择的每个RadioButton
。