2016-12-26 40 views
2

比方说,我有几个单选按钮和一些自定义对象作为数据源。Windows窗体RadioButton列表 - 绑定Enum属性到RadioButton

作为例子

public enum SomeModeType 
{ 
    firstMode = 10, 
    secondMode = 20, 
    thirdMode = 30 
} 

public class MyCustomObject:INotifyPropertyChanged 
{ 

    private SomeModeType _mode; 
    public SomeModeType Mode 
    { 
     set { _mode = value; } 
     get { return _mode; } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

如何此对象属性的东西,如绑定(如果可能)3个不同的单选按钮:

如果radiobuttonOne检查 - 对象属性mode套到firstMode

如果检查radiobuttonTwo - 对象属性mode设置为secondMode

如果radiobuttonThree检查 - 对象属性mode套到thirdMode

等等等等

或其更好地使用这个事件?

P.S. 我知道如何使用活动,但它不知所措,通过像rb1chnagedrb2changed,...,rb100changed这样的事件创建活动,不是吗?

P.P.S.

MerryXmas!

+0

当你在声明枚举类型,它只是一个条目。你需要一个集合来绑定到单选按钮列表。尝试声明'List '作为属性,并填写每个枚举的成员 –

+0

@AnupSharma,但如何帮助? 我的意思是,为什么不直接绑定单选按钮就好像 - 如果选择1st,则字段值将变为firstMode,如果是2nd,则将字段值重写为secondMode – DanilGholtsman

+0

我共享一个RadioButtonList控件[here] (http://stackoverflow.com/a/41355419/3110834)。 –

回答

1

对于枚举的每个值,您需要创建一个RadioButton并将其Checked值绑定到数据源的Mode属性。那么您需要使用FormatParse事件BindingMode值转换为Checked属性的合适值,反之亦然。

实施例 - 单选按钮列表使用FlowLayoutPanel的

例如把一个FlowLayoutPanel控制窗体上,然后在Load事件Form写的以下代码。该代码将动态添加RadioButton控制到流布局面板,并执行数据绑定:

var enumValues = Enum.GetValues(typeof(SomeModeType)).Cast<object>() 
    .Select(x => new { Value = x, Name = x.ToString() }).ToList(); 
enumValues.ForEach(x => 
{ 
    var radio = new RadioButton() { Text = x.Name, Tag = x.Value }; 
    var binding = radio.DataBindings.Add("Checked", dataSource, 
     "Mode", true, DataSourceUpdateMode.OnPropertyChanged); 
    binding.Format += (obj, ea) => 
    { ea.Value = ((Binding)obj).Control.Tag.Equals(ea.Value); }; 
    binding.Parse += (obj, ea) => 
    { if ((bool)ea.Value == true) ea.Value = ((Binding)obj).Control.Tag; }; 
    flowLayoutPanel1.Controls.Add(radio); 
}); 

在上面的例子中,dataSource可以是MyCustomObjectBindingList<MyCustomObject>或含有在其DataSource一个List<MyCustomObject>一个BindingSource。使用重绘列表框

作为另一个选项,您可以使用一个所有者绘制ListBox和项目呈现RadioButton单选按钮列表 -

另一种选择。这样,您可以将SelectedValueListBox绑定到您的对象的Mode属性。以下代码中的dataSourcs可以像上面的例子。穿上形式ListBox写下面的代码Load活动形式:

var enumValues = Enum.GetValues(typeof(SomeModeType)).Cast<object>() 
    .Select(x => new { Value = x, Name = x.ToString() }).ToList(); 
this.listBox1.DataSource = enumValues; 
this.listBox1.ValueMember = "Value"; 
this.listBox1.DisplayMember = "Name"; 
this.listBox1.DataBindings.Add("SelectedValue", dataSource, 
     "Mode", true, DataSourceUpdateMode.OnPropertyChanged); 
this.listBox1.DrawMode = DrawMode.OwnerDrawFixed; 
this.listBox1.ItemHeight = RadioButtonRenderer.GetGlyphSize(
    Graphics.FromHwnd(IntPtr.Zero), 
      RadioButtonState.CheckedNormal).Height + 4; 
this.listBox1.DrawItem += (obj, ea) => 
{ 
    var lb = (ListBox)obj; 
    ea.DrawBackground(); 
    var text = lb.GetItemText(lb.Items[ea.Index]); 
    var r = ea.Bounds; 
    r.Offset(ea.Bounds.Height, 0); 
    RadioButtonRenderer.DrawRadioButton(ea.Graphics, 
     new Point(ea.Bounds.Location.X, ea.Bounds.Location.Y + 2), r, text, 
     lb.Font, TextFormatFlags.Left, false, 
     (ea.State & DrawItemState.Selected) == DrawItemState.Selected ? 
     RadioButtonState.CheckedNormal : RadioButtonState.UncheckedNormal); 
}; 

截图

你可以看到下面的图片这两个解决方案:

enter image description here

var list = new List<MyCustomObject>() { 
    new MyCustomObject(){ Mode= SomeModeType.firstMode}, 
    new MyCustomObject(){ Mode= SomeModeType.secondMode}, 
    new MyCustomObject(){ Mode= SomeModeType.thirdMode}, 
}; 
this.myCustomObjectBindingSource.DataSource = list; 
var dataSource = myCustomObjectBindingSource; 

备注

回答完这个问题后,我在这篇文章中创建并共享了一个RadioButtonList控件:WinForms RadioButtonList doesn't exist

它具有数据绑定支持,您可以使用此控件,如ListBox。要做到这一点,就足以将其绑定到你的模型的属性,然后设置控件只是这样的数据源:

radioButtonList1.DataSource = Enum.GetValues(typeof(YourEnumType)); 
+0

好,有趣,但没有更多的simle方式呢? ._。 – DanilGholtsman

+0

不幸的是,除非将所有逻辑封装在单个控件中,并将其命名为'RadioButtonList',否则没有更简单的方法。 –

+0

另一种选择(根本不那么简单)是使用所有者绘制的Listbox。我也会分享它。 –