实现这一点的方法数量惊人(这就是 WPF 的美妙之处);但是,在我个人看来,如果您只是使用从ToggleButton 派生的控件(例如RadioButton),那么您的工作就会更少“违背常规”,特别是因为您希望它全部在 XAML 中完成。重要的是不要通过视觉来考虑任何控件,而是通过它们的功能来考虑。我以前用RadioButton 做过一些不可思议的事情,所以这是我要演示的第一件事;但是,此答案的后半部分包含常规按钮方法。
以下是两种方法的完整示例(RadioButton 和 Button),完全在 XAML 中完成:
预览:
代码:
<Window x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type RadioButton}" x:Key="FlatRadioButtonStyle">
<Setter Property="Width" Value="100"/>
<Setter Property="Background" Value="#FF346FD6"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Padding" Value="5,2,5,3"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border Background="{TemplateBinding Background}"
Width="{TemplateBinding Width}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}">
<ContentPresenter Content="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#FF6696E9"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<RadioButton x:Name="BackButton" Content="Back">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}" BasedOn="{StaticResource FlatRadioButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=CancelButton}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
<RadioButton x:Name="CancelButton" Content="Cancel" IsChecked="True">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}" BasedOn="{StaticResource FlatRadioButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=BackButton}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
</Grid>
</Window>
大部分资源样式代码是视觉样式和模板,专注于使单选按钮看起来像常规按钮,所以它不是很重要。我们将关注的领域是Triggers。您会注意到,在资源样式中,我确保当 RadioButton 被选中时,它会崩溃。但是,在每个按钮的本地样式中,我确保当另一个RadioButton 被选中时,它使当前的RadioButton 可见。这必须以本地样式完成,因为我们需要将ElementName 传递给Binding。因此,当一个RadioButton 被选中时,它会折叠并使另一个RadioButton 可见。您还会注意到,我选中了我希望默认隐藏的按钮。显然,您可以使用绑定将其连接起来。
类似的方法可以应用于常规按钮:
预览:
代码:
<Window x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type Button}" x:Key="ToggleButtonStyle">
<Setter Property="Width" Value="100"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button x:Name="CancelButton" Content="Cancel">
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource ToggleButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=BackButton}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button x:Name="BackButton" Content="Back">
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource ToggleButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=CancelButton}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</Window>
在这里,我使用的是IsFocused,而不是IsChecked。您可以通过使用EventTrigger 和Click 事件来完成类似的事情......但是,还有更多工作。 IsPressed 可能看起来是一个不错的候选者,但问题是一旦你按下按钮,另一个几乎会立即出现,而那个将几乎瞬间将IsPressed 设置为true。因此,您最终会遇到这种似乎什么都没有发生的循环行为。请注意,我使用Grid 将这些按钮放在彼此的顶部,而我希望默认显示的按钮位于顶部,这样我就不必担心默认的可见性或焦点。但是,您可以使用任何其他面板,只需将您要隐藏的按钮的Visibility 默认设置为Collapsed。
如果您不想使用多个控件(在这种情况下为两个按钮),您还可以通过DataTrigger 根据条件设置按钮的Content 属性以显示不同的文本。您只需确保正确处理Command。