Winforms 将枚举绑定到单选按钮

Posted

技术标签:

【中文标题】Winforms 将枚举绑定到单选按钮【英文标题】:Winforms Bind Enum to Radio Buttons 【发布时间】:2011-01-29 10:17:16 【问题描述】:

如果我有三个单选按钮,将它们绑定到具有相同选择的枚举的最佳方法是什么?例如

[] Choice 1
[] Choice 2
[] Choice 3

public enum MyChoices

    Choice1,
    Choice2,
    Choice3

【问题讨论】:

【参考方案1】:

我知道这是一个老问题,但它是第一个出现在我的搜索结果中的问题。我想出了一种将单选按钮绑定到枚举,甚至是字符串或数字等的通用方法。

    private void AddRadioCheckedBinding<T>(RadioButton radio, object dataSource, string dataMember, T trueValue)
    
        var binding = new Binding(nameof(RadioButton.Checked), dataSource, dataMember, true, DataSourceUpdateMode.OnPropertyChanged);
        binding.Parse += (s, a) =>  if ((bool)a.Value) a.Value = trueValue; ;
        binding.Format += (s, a) => a.Value = ((T)a.Value).Equals(trueValue);
        radio.DataBindings.Add(binding);
    

然后在表单的构造函数或表单加载事件上,在每个RadioButton 控件上调用它。 dataSource 是包含您的枚举属性的对象。我确保dataSource 实现了INotifyPropertyChanged 接口在枚举属性设置器中触发OnPropertyChanged 事件。

AddRadioCheckedBinding(Choice1RadioButton, dataSource, "MyChoice", MyChoices.Choice1);
AddRadioCheckedBinding(Choice2RadioButton, dataSource, "MyChoice", MyChoices.Choice2);

【讨论】:

伙计,这是救命的!几乎试图创建另一个配置文件只是为了 UpVote 两次!当然,我将其转换为扩展方法:public static void AddRadioCheckedBinding&lt;T&gt;(this RadioButton radio, object dataSource, string dataMember, T trueValue)【参考方案2】:

你能不能创建三个布尔属性:

private MyChoices myChoice;

public bool MyChoice_Choice1

    get  return myChoice == MyChoices.Choice1; 
    set  if (value) myChoice = MyChoices.Choice1; myChoiceChanged(); 


// and so on for the other two

private void myChoiceChanged()

    OnPropertyChanged(new PropertyChangedEventArgs("MyChoice_Choice1"));
    OnPropertyChanged(new PropertyChangedEventArgs("MyChoice_Choice2"));
    OnPropertyChanged(new PropertyChangedEventArgs("MyChoice_Choice3"));

然后绑定到 MyChoice_Choice1 和其他?

【讨论】:

【参考方案3】:

我只是想我会添加我目前正在做的方式。没有这样的“绑定”,但希望它能起到同样的作用。

欢迎评论。

public enum MyChoices

    Choice1,
    Choice2,
    Choice3


public partial class Form1 : Form

    private Dictionary<int, RadioButton> radButtons;
    private MyChoices choices;

    public Form1()
    
        this.InitializeComponent();
        this.radButtons = new Dictionary<int, RadioButton>();
        this.radButtons.Add(0, this.radioButton1);
        this.radButtons.Add(1, this.radioButton2);
        this.radButtons.Add(2, this.radioButton3);

        foreach (var item in this.radButtons)
        
            item.Value.CheckedChanged += new EventHandler(RadioButton_CheckedChanged);
        
    

    private void RadioButton_CheckedChanged(object sender, EventArgs e)
    
        RadioButton button = sender as RadioButton;
        foreach (var item in this.radButtons)
        
            if (item.Value == button)
            
                this.choices = (MyChoices)item.Key;
            
        
    

    public MyChoices Choices
    
        get  return this.choices; 
        set
        
            this.choices = value;
            this.SelectRadioButton(value);
            this.OnPropertyChanged(new PropertyChangedEventArgs("Choices"));
        
    

    private void SelectRadioButton(MyChoices choiceID)
    
        RadioButton button;
        this.radButtons.TryGetValue((int)choiceID, out button);
        button.Checked = true;
    

【讨论】:

【参考方案4】:

问题发布者没有提及他绑定的内容。我想他绑定到 XXX.Properties.Settings 类。如果没有,这个方案需要绑定类来实现INotifyPropertyChanged接口。

并且有一个这样的索引器:

public object this[string propertyName]  get; set; 

我尝试了 WeskerTyrant 提供的公认解决方案,但失败了。

我必须点击两次才能工作。

于是我开始自己解决问题。我注意到我绑定的类实现了 INotifyPropertyChanged 接口。其中有一个名为 PropertyChangedPropertyChangedEventHandler

(顺便说一下,我使用的是 .net 472) 所以我自己写了一个辅助类。

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Windows.Forms;
namespace Ezfx.Dui

    public static class RadioButtonGroupUI
    
        public static void Apply(ApplicationSettingsBase settings, string key, Control parentControl)
        
            List<RadioButton> radios = new List<RadioButton>();
            foreach(Control control in parentControl.Controls)
            
                switch (control)
                
                    case RadioButton e:
                        radios.Add(e);
                        break;
                
            

            Apply(settings, key, radios.ToArray());
        

        public static void Apply(ApplicationSettingsBase settings, string key, params RadioButton[] radios)
        

            foreach (RadioButton radioButton in radios)
            
                if (radioButton.Text == (string)settings[key])
                
                    radioButton.Checked = true;
                

                radioButton.CheckedChanged += (sender, e) => 
                    if (radioButton.Checked)
                    
                        settings[key] = radioButton.Text;
                    
                    
                ;
            

            settings.PropertyChanged += (sender, e) =>
            
                foreach (RadioButton radioButton in radios)
                
                    if (radioButton.Text == (string)settings[key])
                    
                        radioButton.Checked = true;
                    
                    else
                    
                        radioButton.Checked = false;
                    
                
            ;
        
    

使用时。您只需在 form_load 事件中添加以下代码即可。

    private void MainForm_Load(object sender, EventArgs e)
    
        RadioButtonGroupUI.Apply(settings, "category", categoryGroupBox);
        RadioButtonGroupUI.Apply(settings, "package", scikitLearnRadioButton, sparkRadioButton);
    

我在 github 上分享了这个:

https://github.com/EricWebsmith/Ezfx.Dui

我猜人们会否决我,因为这不能回答有关枚举的问题。我的解决方案是在使用时强制转换设置。就我而言,我使用 python 脚本中的设置,所以不需要强制转换。

Enum.TryParse(settings.category, out Category category);

【讨论】:

以上是关于Winforms 将枚举绑定到单选按钮的主要内容,如果未能解决你的问题,请参考以下文章

ItemsControl 上的 WPF MVVM 单选按钮

mvc 绑定/发布布尔到单选按钮

AngularJS:将布尔值绑定到单选按钮,以便在取消选中事件时将模型更新为 false

Aurelia在检查更改时将值绑定到单选按钮

在 WinForms 中对一组单选按钮进行数据绑定的最佳方法

如何将侦听器附加到单选按钮