WPF XAML中RadioGroup内RadioButton的自定义悬停与选中效果问题
一、已选中按钮的悬停效果修复
你的悬停触发条件限定了IsChecked=False,导致已选中的按钮永远无法触发悬停规则。需要新增一个针对已选中状态下鼠标悬停的触发器,让选中的按钮在鼠标移上去时也能切换颜色:
在原有的ControlTemplate.Triggers中添加以下MultiTrigger:
<MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsEnabled" Value="True"/> <Condition Property="IsChecked" Value="True"/> <Condition Property="IsMouseOver" Value="True"/> </MultiTrigger.Conditions> <MultiTrigger.EnterActions> <BeginStoryboard> <Storyboard x:Name="EnterSelectedRadioButtonHover"> <ColorAnimation Storyboard.TargetName="ToggleColor" Storyboard.TargetProperty="Color" To="{StaticResource Hover}" Duration="0:0:0.2" /> </Storyboard> </BeginStoryboard> </MultiTrigger.EnterActions> <MultiTrigger.ExitActions> <BeginStoryboard> <Storyboard x:Name="ExitSelectedRadioButtonHover"> <ColorAnimation Storyboard.TargetName="ToggleColor" Storyboard.TargetProperty="Color" To="{StaticResource Selected}" Duration="0:0:0.2" /> </Storyboard> </BeginStoryboard> </MultiTrigger.ExitActions> </MultiTrigger>
修改后,已选中的按钮在鼠标悬停时会切换到Hover颜色,移开后回到选中的绿色。
二、点击已选中按钮取消选中(组内无选中项)
RadioButton默认单选逻辑不支持取消选中,需要自定义点击行为,以下是两种实现方式:
方式1:后台代码处理Click事件
给每个RadioButton绑定Click事件,在事件处理方法中判断如果当前按钮已选中,就将其设为未选中:
private void RadioButton_Click(object sender, RoutedEventArgs e) { var radioBtn = sender as RadioButton; if (radioBtn != null && radioBtn.IsChecked == true) { radioBtn.IsChecked = false; } }
在XAML的RadioButton上添加Click="RadioButton_Click"即可生效。
方式2:附加行为(MVVM友好)
如果使用MVVM模式,可通过附加属性实现无耦合的取消逻辑:
public static class RadioButtonHelper { public static readonly DependencyProperty AllowUncheckProperty = DependencyProperty.RegisterAttached("AllowUncheck", typeof(bool), typeof(RadioButtonHelper), new PropertyMetadata(false, OnAllowUncheckChanged)); public static bool GetAllowUncheck(DependencyObject obj) { return (bool)obj.GetValue(AllowUncheckProperty); } public static void SetAllowUncheck(DependencyObject obj, bool value) { obj.SetValue(AllowUncheckProperty, value); } private static void OnAllowUncheckChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is RadioButton radioBtn) { if ((bool)e.NewValue) { radioBtn.Click += RadioBtn_Click; } else { radioBtn.Click -= RadioBtn_Click; } } } private static void RadioBtn_Click(object sender, RoutedEventArgs e) { var radioBtn = sender as RadioButton; if (radioBtn?.IsChecked == true) { radioBtn.IsChecked = false; e.Handled = true; } } }
在XAML中引用该附加属性:
<RadioButton Style="{StaticResource CustomRadioButton}" local:RadioButtonHelper.AllowUncheck="True" Content="选项1"/>
完整修改后的Style代码
<Color x:Key="Hover" R="135" G="0" B="0" A="255" /> <Color x:Key="Default" R="40" G="40" B="40" A="255" /> <Color x:Key="Selected" R="0" G="255" B="0" A="255" /> <!-- // CustomRadioButton // --> <Style TargetType="{x:Type RadioButton}" x:Key="CustomRadioButton"> <Style.Setters> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="RadioButton"> <Border x:Name="tabRadBtn" Margin="10" Width="60" BorderThickness="0"> <TextBlock Background="Transparent" x:Name="ToggleData" Text="{TemplateBinding Property=Content}" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock.Foreground> <SolidColorBrush x:Name="ToggleColor" Color="{StaticResource Default}"/> </TextBlock.Foreground> </TextBlock> </Border> <ControlTemplate.Triggers> <!-- 未选中时的悬停 --> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsEnabled" Value="True"/> <Condition Property="IsChecked" Value="False"/> <Condition Property="IsMouseOver" Value="True"/> </MultiTrigger.Conditions> <MultiTrigger.EnterActions> <BeginStoryboard> <Storyboard x:Name="EnterRadioButtonHover"> <ColorAnimation Storyboard.TargetName="ToggleColor" Storyboard.TargetProperty="Color" To="{StaticResource Hover}" Duration="0:0:0.2" /> </Storyboard> </BeginStoryboard> </MultiTrigger.EnterActions> <MultiTrigger.ExitActions> <BeginStoryboard> <Storyboard x:Name="ExitRadioButtonHover"> <ColorAnimation Storyboard.TargetName="ToggleColor" Storyboard.TargetProperty="Color" To="{StaticResource Default}" Duration="0:0:0.2" /> </Storyboard> </BeginStoryboard> </MultiTrigger.ExitActions> </MultiTrigger> <!-- 选中状态 --> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsChecked" Value="True"/> <Condition Property="IsEnabled" Value="True"/> </MultiTrigger.Conditions> <MultiTrigger.EnterActions> <BeginStoryboard> <Storyboard x:Name="EnterRadioButtonSelect"> <ColorAnimation Storyboard.TargetName="ToggleColor" Storyboard.TargetProperty="Color" To="{StaticResource Selected}" Duration="0:0:0.2" /> </Storyboard> </BeginStoryboard> </MultiTrigger.EnterActions> <MultiTrigger.ExitActions> <BeginStoryboard> <Storyboard x:Name="ExitRadioButtonSelect"> <ColorAnimation Storyboard.TargetName="ToggleColor" Storyboard.TargetProperty="Color" To="{StaticResource Default}" Duration="0:0:0.2" /> </Storyboard> </BeginStoryboard> </MultiTrigger.ExitActions> </MultiTrigger> <!-- 已选中时的悬停 --> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsEnabled" Value="True"/> <Condition Property="IsChecked" Value="True"/> <Condition Property="IsMouseOver" Value="True"/> </MultiTrigger.Conditions> <MultiTrigger.EnterActions> <BeginStoryboard> <Storyboard x:Name="EnterSelectedRadioButtonHover"> <ColorAnimation Storyboard.TargetName="ToggleColor" Storyboard.TargetProperty="Color" To="{StaticResource Hover}" Duration="0:0:0.2" /> </Storyboard> </BeginStoryboard> </MultiTrigger.EnterActions> <MultiTrigger.ExitActions> <BeginStoryboard> <Storyboard x:Name="ExitSelectedRadioButtonHover"> <ColorAnimation Storyboard.TargetName="ToggleColor" Storyboard.TargetProperty="Color" To="{StaticResource Selected}" Duration="0:0:0.2" /> </Storyboard> </BeginStoryboard> </MultiTrigger.ExitActions> </MultiTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style.Setters> </Style>
内容的提问来源于stack exchange,提问作者user19666465
相关产品推荐
相关产品推荐

