WPF RadioButton 控件全面教程:从基础到高级应用
<Window x:Class="WPF之RadioButton.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF之RadioButton"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<RadioButton x:Name="rbn1" Checked="rbn_Checked" IsChecked="True" > 硬触发</RadioButton>
<RadioButton x:Name="rbn2" Checked="rbn_Checked" >软触发</RadioButton>
<RadioButton GroupName="g1" Checked="rbn_Checked" IsChecked="True" >男</RadioButton>
<RadioButton GroupName="g1" Checked="rbn_Checked" >女</RadioButton>
<TextBox x:Name="txt1"></TextBox>
</StackPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WPF之RadioButton
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void rbn1_Checked(object sender, RoutedEventArgs e)
{
}
private void rbn_Checked(object sender, RoutedEventArgs e)
{
RadioButton radioButton = (RadioButton)sender;
if(radioButton!=null && radioButton.Content!=null)
{
txt1.Text = radioButton.Content.ToString();
}
}
}
}
分组
<RadioButton GroupName="Theme" Content="浅色" IsChecked="True" Margin="0,0,0,5"/>
<RadioButton GroupName="Theme" Content="深色" Margin="0,0,0,5"/>
<RadioButton GroupName="Theme" Content="系统默认" Margin="0,0,0,20"/>
RadioButton 是 WPF 中用于实现单选功能的控件,通常用于让用户在多个互斥选项中选择一个。相比 WinForms,WPF 的 RadioButton 支持数据绑定、样式定制、模板化和 MVVM 模式,能够更灵活地适应复杂界面需求。本教程将带你从基础用法到高级技巧,全面掌握 RadioButton 的核心能力。
一、RadioButton 基础用法
1. 基本属性
- GroupName:定义单选组的名称(同一组内的 RadioButton 互斥)。
- IsChecked:绑定或设置是否选中(
true
或false
)。 - Content:设置单选按钮旁边的文本标签。
- IsEnabled:是否禁用控件。
- HorizontalAlignment/VerticalAlignment:控制控件对齐方式。
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="RadioButton 基础示例" Height="300" Width="400">
<StackPanel Margin="20">
<!-- 单选组1 -->
<TextBlock Text="选择性别:" Margin="0,0,0,10"/>
<RadioButton GroupName="Gender" Content="男" Margin="0,0,0,5"/>
<RadioButton GroupName="Gender" Content="女" Margin="0,0,0,5"/>
<RadioButton GroupName="Gender" Content="其他" Margin="0,0,0,20"/>
<!-- 单选组2 -->
<TextBlock Text="选择主题:" Margin="0,0,0,10"/>
<RadioButton GroupName="Theme" Content="浅色" IsChecked="True" Margin="0,0,0,5"/>
<RadioButton GroupName="Theme" Content="深色" Margin="0,0,0,5"/>
<RadioButton GroupName="Theme" Content="系统默认" Margin="0,0,0,20"/>
<!-- 禁用状态 -->
<RadioButton GroupName="DisabledGroup" Content="不可用选项" IsEnabled="False"/>
</StackPanel>
</Window>
2. 常用事件
- Checked:单选按钮被选中时触发。
- Unchecked:单选按钮被取消选中时触发(但同一组内其他按钮选中时也会触发)。
- Click:点击时触发(无论状态是否变化)。
<RadioButton GroupName="Example" Content="选项1" Margin="0,0,0,10"
Checked="RadioButton_Checked"
Unchecked="RadioButton_Unchecked"
Click="RadioButton_Click"/>
private void RadioButton_Checked(object sender, RoutedEventArgs e)
{
if (sender is RadioButton radioButton)
{
MessageBox.Show($"已选中: {radioButton.Content}");
}
}
private void RadioButton_Unchecked(object sender, RoutedEventArgs e)
{
Debug.WriteLine("某个单选按钮被取消选中");
}
private void RadioButton_Click(object sender, RoutedEventArgs e)
{
if (sender is RadioButton radioButton)
{
Debug.WriteLine($"当前值: {radioButton.IsChecked}");
}
}
二、RadioButton 高级功能
1. 数据绑定(MVVM 模式)
通过 Binding
将 RadioButton 的 IsChecked
绑定到 ViewModel 的属性,实现双向数据同步。
<!-- XAML -->
<StackPanel Margin="20">
<TextBlock Text="选择语言:" Margin="0,0,0,10"/>
<RadioButton GroupName="Language" Content="中文" Margin="0,0,0,5"
IsChecked="{Binding SelectedLanguage, Converter={StaticResource EqualToConverter}, ConverterParameter=Chinese}"/>
<RadioButton GroupName="Language" Content="英文" Margin="0,0,0,5"
IsChecked="{Binding SelectedLanguage, Converter={StaticResource EqualToConverter}, ConverterParameter=English}"/>
<RadioButton GroupName="Language" Content="日文" Margin="0,0,0,20"
IsChecked="{Binding SelectedLanguage, Converter={StaticResource EqualToConverter}, ConverterParameter=Japanese}"/>
</StackPanel>
// ViewModel 示例
public class MainViewModel : INotifyPropertyChanged
{
private string _selectedLanguage;
public string SelectedLanguage
{
get => _selectedLanguage;
set
{
_selectedLanguage = value;
OnPropertyChanged();
Debug.WriteLine($"当前语言: {value}");
}
}
public MainViewModel()
{
SelectedLanguage = "Chinese"; // 默认选中中文
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
2. 自定义值绑定(使用 Value 属性)
通过 Tag
或自定义附加属性绑定实际值。
<!-- 定义附加属性(在代码中实现) -->
<Window.Resources>
<Style TargetType="RadioButton">
<Setter Property="local:RadioButtonHelper.Value" Value="{Binding Content}"/>
</Style>
</Window.Resources>
<StackPanel Margin="20">
<TextBlock Text="选择颜色:" Margin="0,0,0,10"/>
<RadioButton GroupName="Color" Content="红色" Margin="0,0,0,5"
IsChecked="{Binding SelectedColor, Converter={StaticResource EqualToConverter}, ConverterParameter=红色}"/>
<RadioButton GroupName="Color" Content="绿色" Margin="0,0,0,5"
IsChecked="{Binding SelectedColor, Converter={StaticResource EqualToConverter}, ConverterParameter=绿色}"/>
<RadioButton GroupName="Color" Content="蓝色" Margin="0,0,0,20"
IsChecked="{Binding SelectedColor, Converter={StaticResource EqualToConverter}, ConverterParameter=蓝色}"/>
</StackPanel>
// 附加属性实现(简化版)
public static class RadioButtonHelper
{
public static readonly DependencyProperty ValueProperty =
DependencyProperty.RegisterAttached(
"Value", typeof(object), typeof(RadioButtonHelper), new PropertyMetadata(null));
public static void SetValue(DependencyObject element, object value) =>
element.SetValue(ValueProperty, value);
public static object GetValue(DependencyObject element) =>
element.GetValue(ValueProperty);
}
3. 命令绑定(Command)
通过 Command
绑定到 ViewModel 的 ICommand 实现逻辑处理。
<!-- XAML -->
<StackPanel Margin="20">
<TextBlock Text="选择字体大小:" Margin="0,0,0,10"/>
<RadioButton GroupName="FontSize" Content="小" Margin="0,0,0,5"
IsChecked="{Binding SelectedFontSize, Converter={StaticResource EqualToConverter}, ConverterParameter=Small}"
Command="{Binding FontSizeChangedCommand}"
CommandParameter="Small"/>
<RadioButton GroupName="FontSize" Content="中" Margin="0,0,0,5"
IsChecked="{Binding SelectedFontSize, Converter={StaticResource EqualToConverter}, ConverterParameter=Medium}"
Command="{Binding FontSizeChangedCommand}"
CommandParameter="Medium"/>
<RadioButton GroupName="FontSize" Content="大" Margin="0,0,0,20"
IsChecked="{Binding SelectedFontSize, Converter={StaticResource EqualToConverter}, ConverterParameter=Large}"
Command="{Binding FontSizeChangedCommand}"
CommandParameter="Large"/>
</StackPanel>
// ViewModel 示例
public class MainViewModel : INotifyPropertyChanged
{
private string _selectedFontSize;
public string SelectedFontSize
{
get => _selectedFontSize;
set
{
_selectedFontSize = value;
OnPropertyChanged();
}
}
public ICommand FontSizeChangedCommand { get; }
public MainViewModel()
{
SelectedFontSize = "Medium"; // 默认选中中等
FontSizeChangedCommand = new RelayCommand<string>(OnFontSizeChanged);
}
private void OnFontSizeChanged(string size)
{
Debug.WriteLine($"字体大小已更改为: {size}");
// 执行其他逻辑(如更新界面字体)
}
// RelayCommand 实现(简化版)
public class RelayCommand<T> : ICommand
{
private readonly Action<T> _execute;
private readonly Predicate<T> _canExecute;
public RelayCommand(Action<T> execute, Predicate<T> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null || _canExecute((T)parameter);
public void Execute(object parameter) => _execute((T)parameter);
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
三、RadioButton 样式与模板定制
1. 简单样式重用
通过 Style
定义可复用的单选按钮样式。
<Window.Resources>
<Style x:Key="CustomRadioButton" TargetType="RadioButton">
<Setter Property="Foreground" Value="DarkBlue"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<BulletDecorator Background="Transparent">
<BulletDecorator.Bullet>
<Grid Width="16" Height="16">
<Ellipse x:Name="OuterCircle"
Stroke="Gray"
StrokeThickness="2"
Fill="White"/>
<Ellipse x:Name="InnerCircle"
Width="8" Height="8"
Fill="Green"
Visibility="Collapsed"/>
</Grid>
</BulletDecorator.Bullet>
<ContentPresenter Margin="5,0,0,0"
VerticalAlignment="Center"/>
</BulletDecorator>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="InnerCircle" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="OuterCircle" Property="Stroke" Value="Blue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<RadioButton Content="自定义样式1" Style="{StaticResource CustomRadioButton}" Margin="0,0,0,10"/>
<RadioButton Content="自定义样式2" Style="{StaticResource CustomRadioButton}" Margin="0,0,0,20"/>
</StackPanel>
2. 动态样式切换
通过 DataTrigger
根据状态切换样式。
<RadioButton Content="动态样式" Margin="0,0,0,20">
<RadioButton.Style>
<Style TargetType="RadioButton">
<Setter Property="Foreground" Value="Black"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Foreground" Value="Green"/>
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Blue"/>
</Trigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
四、RadioButton 高级应用场景
1. 关联其他控件
通过数据绑定或命令控制其他控件的启用/禁用状态。
<StackPanel Margin="20">
<TextBlock Text="选择显示模式:" Margin="0,0,0,10"/>
<RadioButton GroupName="DisplayMode" Content="简洁模式" Margin="0,0,0,5"
IsChecked="{Binding SelectedDisplayMode, Converter={StaticResource EqualToConverter}, ConverterParameter=Simple}"/>
<RadioButton GroupName="DisplayMode" Content="详细模式" Margin="0,0,0,20"
IsChecked="{Binding SelectedDisplayMode, Converter={StaticResource EqualToConverter}, ConverterParameter=Detailed}"/>
<!-- 根据选择显示不同内容 -->
<TextBox Text="简洁模式内容" Margin="0,0,0,10"
Visibility="{Binding SelectedDisplayMode, Converter={StaticResource EqualToVisibilityConverter}, ConverterParameter=Simple}"/>
<RichTextBox Margin="0,0,0,10"
Visibility="{Binding SelectedDisplayMode, Converter={StaticResource EqualToVisibilityConverter}, ConverterParameter=Detailed}">
<FlowDocument>
<Paragraph>详细模式内容...</Paragraph>
</FlowDocument>
</RichTextBox>
</StackPanel>
2. 批量操作
通过 ItemsControl
绑定一组 RadioButton 实现动态生成选项。
<ListBox ItemsSource="{Binding DisplayModes}" Margin="0,0,0,20">
<ListBox.ItemTemplate>
<DataTemplate>
<RadioButton GroupName="DynamicModes" Content="{Binding Name}" Margin="0,0,0,5"
IsChecked="{Binding IsSelected, Mode=TwoWay}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
// ViewModel 示例
public class DisplayMode
{
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public class MainViewModel : INotifyPropertyChanged
{
public ObservableCollection<DisplayMode> DisplayModes { get; } = new ObservableCollection<DisplayMode>
{
new DisplayMode { Name = "模式1" },
new DisplayMode { Name = "模式2" },
new DisplayMode { Name = "模式3" }
};
// ... 其他代码 ...
}
3. 自定义模板(带图标)
通过 ControlTemplate
添加图标或动画效果。
<RadioButton Content="带图标的单选按钮" Margin="0,0,0,20">
<RadioButton.Template>
<ControlTemplate TargetType="RadioButton">
<StackPanel Orientation="Horizontal">
<Border Width="16" Height="16" Background="White" BorderBrush="Gray" BorderThickness="1">
<Ellipse x:Name="SelectedCircle" Width="8" Height="8" Fill="Green" Visibility="Collapsed"/>
</Border>
<Image Source="icon.png" Width="16" Height="16" Margin="5,0,0,0"/>
<ContentPresenter Margin="5,0,0,0" VerticalAlignment="Center"/>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="SelectedCircle" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</RadioButton.Template>
</RadioButton>
五、总结
- 核心功能:
- 通过
GroupName
实现单选组。 - 支持数据绑定和命令绑定,适合 MVVM 模式。
- 支持事件触发(Checked、Unchecked、Click)。
- 通过
- 高级技巧:
- 通过
Style
和ControlTemplate
完全自定义外观。 - 结合
ItemsControl
实现动态生成选项。 - 通过
DataTrigger
实现动态样式切换。
- 通过
- 扩展学习:
- 学习
ToggleButton
的基础(RadioButton 继承自 ToggleButton)。 - 掌握
ValueConverter
的使用(如EqualToConverter
)。 - 了解
DataTemplate
和ItemsControl
的高级用法。
- 学习
通过掌握 RadioButton 的高级用法,你可以轻松创建交互丰富、功能强大的 WPF 界面。建议结合实际项目需求,灵活运用样式和模板!