WPF之RadioButton

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:绑定或设置是否选中(truefalse)。
  • 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>

五、总结
  1. 核心功能
    • 通过 GroupName 实现单选组。
    • 支持数据绑定和命令绑定,适合 MVVM 模式。
    • 支持事件触发(Checked、Unchecked、Click)。
  2. 高级技巧
    • 通过 StyleControlTemplate 完全自定义外观。
    • 结合 ItemsControl 实现动态生成选项。
    • 通过 DataTrigger 实现动态样式切换。
  3. 扩展学习
    • 学习 ToggleButton 的基础(RadioButton 继承自 ToggleButton)。
    • 掌握 ValueConverter 的使用(如 EqualToConverter)。
    • 了解 DataTemplateItemsControl 的高级用法。

通过掌握 RadioButton 的高级用法,你可以轻松创建交互丰富、功能强大的 WPF 界面。建议结合实际项目需求,灵活运用样式和模板!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值