Let's say I got few radiobuttons and some custom object as datasource.
As example
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));
}
}
}
How to bind this object property (if its possible) to 3 different radiobuttons with something like:
If radiobuttonOne
checked - object property mode
sets to firstMode
If radiobuttonTwo
checked - object property mode
sets to secondMode
If radiobuttonThree
checked - object property mode
sets to thirdMode
etc etc
Or its better to use events for this?
P.S.
I know how to use events but its overwhelmed to create event by event like rb1chnaged
, rb2changed
, ..., rb100changed
, isnt it?
P.P.S.
MerryXmas!
For each value of the enum, you need to create a RadioButton
and bind its Checked
value to Mode
property of data source. Then you need to use Format
and Parse
event of Binding
to convert Mode
value to suitable value for Checked
property and vise versa.
Example - RadioButton List using FlowLayoutPanel
For example put a FlowLayoutPanel
control on your form and then in Load
event of Form
write following code. The code will add RadioButton
controls to the flow layout panel dynamically and performs data-binding:
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);
});
In above example, dataSource
can be a MyCustomObject
or a BindingList<MyCustomObject>
or a BindingSource
which contains a List<MyCustomObject>
in its DataSource
.
Another alternative - RadioButton List using Owner-draw ListBox
As another option you can use an owner-draw ListBox
and render RadioButton
for items. This way, you can bind SelectedValue
of ListBox
to Mode
property of your object. The dataSourcs
in following code can be like above example. Put a ListBox
on form and write following code in Load
event of form:
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);
};
Screenshot
You can see both solutions in following image:
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;
Note
After answering this question, I created and shared a RadioButtonList
control in this post: WinForms RadioButtonList doesn't exist.
It has data-binding support and you can use this control like a ListBox
. To do so, it's enough to bind it to the property of your model, and then set the data-source of the control simply this way:
radioButtonList1.DataSource = Enum.GetValues(typeof(YourEnumType));