WinUI3中如何为按钮设置选中、悬浮、点击时的不同颜色
WinUI实现单选按钮组(带自定义样式)
解决你遇到的问题,核心是用ToggleButton替代普通Button:它自带选中/未选中状态,且通过GroupName属性可自动实现同组单选互斥,不用手动写按钮重置逻辑。以下是具体实现步骤:
1. 替换按钮为ToggleButton并设置分组
把原来的Button换成ToggleButton,给同组按钮设置相同的GroupName,这样点击其中一个时,同组其他ToggleButton会自动取消选中:
<ToggleButton Style="{StaticResource RadioToggleButtonStyle}" Grid.Row="0" Grid.Column="0" Height="40" HorizontalAlignment="Stretch" Content="InRegion" x:Name="InRegion" GroupName="RegionGroup"/> <ToggleButton Style="{StaticResource RadioToggleButtonStyle}" Grid.Row="0" Grid.Column="2" Height="40" HorizontalAlignment="Stretch" Content="OutRegion" x:Name="OutRegion" GroupName="RegionGroup"/>
2. 修改样式支持选中状态
ToggleButton内置CheckStates视觉状态组(包含Checked/Unchecked/Indeterminate),你只需要在样式中添加这个组的状态逻辑即可,不用自己定义不存在的Selected状态:
<Style x:Key="RadioToggleButtonStyle" BasedOn="{StaticResource DefaultToggleButtonStyle}" TargetType="ToggleButton"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ToggleButton"> <Grid x:Name="RootGrid" Background="{TemplateBinding Background}"> <Border BorderThickness="1" BorderBrush="LightGray" CornerRadius="3"> <Rectangle x:Name="ButtonBase" Fill="#fbfbfb" /> </Border> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /> <VisualStateManager.VisualStateGroups> <!-- 保留你原来的悬浮、按压、禁用状态 --> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal" /> <VisualState x:Name="PointerOver"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonBase" Storyboard.TargetProperty="Fill"> <DiscreteObjectKeyFrame KeyTime="0" Value="yellow" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Pressed"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonBase" Storyboard.TargetProperty="Fill"> <DiscreteObjectKeyFrame KeyTime="0" Value="ForestGreen" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Disabled"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonBase" Storyboard.TargetProperty="Fill"> <DiscreteObjectKeyFrame KeyTime="0" Value="DarkOliveGreen" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> <!-- 添加ToggleButton专属的选中状态组 --> <VisualStateGroup x:Name="CheckStates"> <VisualState x:Name="Unchecked" /> <VisualState x:Name="Checked"> <Storyboard> <!-- 设置选中时的背景色 --> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonBase" Storyboard.TargetProperty="Fill"> <DiscreteObjectKeyFrame KeyTime="0" Value="LightSeaGreen" /> </ObjectAnimationUsingKeyFrames> <!-- 设置选中时的文字颜色 --> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground"> <DiscreteObjectKeyFrame KeyTime="0" Value="White" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Indeterminate" /> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
3. 简化后台代码
因为ToggleButton的GroupName已经自动处理了单选互斥,你不需要再写按钮重置逻辑,只需要在点击事件中处理业务逻辑即可:
private void buttonsRegion_click(object sender, RoutedEventArgs e) { var selectedToggle = sender as ToggleButton; if (selectedToggle?.IsChecked == true) { // 这里处理选中后的业务操作,比如获取选中项的值 string selectedContent = selectedToggle.Content.ToString(); // ... 你的业务代码 } }
说明
普通Button确实没有Selected状态,你手动添加的VisualState不会被控件触发,因为控件本身没有对应的状态切换逻辑。而ToggleButton不仅自带选中状态,还支持分组互斥,完全匹配你需要的单选按钮组需求,且样式可以统一复用给不同的按钮组(只需给不同组设置不同的GroupName即可)。
内容的提问来源于stack exchange,提问作者Mateusz Marczewski
相关产品推荐
相关产品推荐

