Winforms Radiobuttonlist Doesn't Exist

WinForms RadioButtonList doesn't exist?

Apparently not.

You can group three RadioButtons together using a GroupBox or a Panel as is done here.

Third party controls for a radio button list in WinForms?

Control vendors can't make any money with controls like that. Here's some code to get your started:

using System;
using System.Drawing;
using System.Windows.Forms;

class RadioList : ListBox {
public event EventHandler SelectedOptionChanged;

public RadioList() {
this.DrawMode = DrawMode.OwnerDrawFixed;
this.ItemHeight += 2;
}
public int SelectedOption {
// Current item with the selected radio button
get { return mSelectedOption; }
set {
if (value != mSelectedOption) {
Invalidate(GetItemRectangle(mSelectedOption));
mSelectedOption = value;
OnSelectedOptionChanged(EventArgs.Empty);
Invalidate(GetItemRectangle(value));
}
}
}
protected virtual void OnSelectedOptionChanged(EventArgs e) {
// Raise SelectOptionChanged event
EventHandler handler = this.SelectedOptionChanged;
if (handler != null) handler(this, e);
}
protected override void OnDrawItem(DrawItemEventArgs e) {
// Draw item with radio button
using (var br = new SolidBrush(this.BackColor))
e.Graphics.FillRectangle(br, e.Bounds);
if (e.Index < this.Items.Count) {
Rectangle rc = new Rectangle(e.Bounds.Left, e.Bounds.Top, e.Bounds.Height, e.Bounds.Height);
ControlPaint.DrawRadioButton(e.Graphics, rc,
e.Index == SelectedOption ? ButtonState.Checked : ButtonState.Normal);
rc = new Rectangle(rc.Right, e.Bounds.Top, e.Bounds.Width - rc.Right, e.Bounds.Height);
TextRenderer.DrawText(e.Graphics, this.Items[e.Index].ToString(), this.Font, rc, this.ForeColor, TextFormatFlags.Left);
}
if ((e.State & DrawItemState.Focus) != DrawItemState.None) e.DrawFocusRectangle();
}
protected override void OnMouseUp(MouseEventArgs e) {
// Detect clicks on the radio button
int index = this.IndexFromPoint(e.Location);
if (index >= 0 && e.X < this.ItemHeight) SelectedOption = index;
base.OnMouseUp(e);
}
protected override void OnKeyDown(KeyEventArgs e) {
// Turn on option with space bar
if (e.KeyData == Keys.Space && this.SelectedIndex >= 0) SelectedOption = this.SelectedIndex;
base.OnKeyDown(e);
}
private int mSelectedOption;
}

Windows Forms RadioButton List - Bind Enum Property to RadioButton

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:

Sample 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)); 

Is there a better way to run through radio buttons in an if statement?

If you have more than say 4 radio buttons (in a group), I think it is better to use a combobox or a list instead.

Otherwise for maintenance purpose, it will be better to somehow use a loop. There are many way to get the controls.

  • You could initialize an array that contains all controls in a group. Something like:

    var group1radios = new RadioButton[] { radio1, radio2, radio 3, radio4 };
  • You could enumerate controls on your form and somehow detect if the control is a radio button belonging to your group (by position, groupbox, tag, name, consecutive radios…).

  • You could create a panel that contains only radio buttons.

Is there a way to control all radio buttons through one control? Instead of passing a control for each radio button (C#)

Simply subscribe all radio buttons to the same event. Then you can act on which is checked and act accordingly instead of having duplicate code for each button.

Below is a simple example that set a text box's Text property to display which is checked.

Form class

public partial class Form1 : Form
{

public Form1()
{
InitializeComponent();
}

private void radioButtons_CheckedChanged(object sender, EventArgs e)
{
//Do whatever you need to do here. I'm simple setting some text based off
//the name of the checked radio button.

System.Windows.Forms.RadioButton rb = (sender as System.Windows.Forms.RadioButton);
textBox1.Text = $"{rb.Name} is checked!";
}
}

In the .designer.cs file

//Note that the EventHandler for each is the same.
this.radioButton3.CheckedChanged += new System.EventHandler(this.radioButtons_CheckedChanged);
this.radioButton2.CheckedChanged += new System.EventHandler(this.radioButtons_CheckedChanged);
this.radioButton1.CheckedChanged += new System.EventHandler(this.radioButtons_CheckedChanged);

C# checkedlistbox with radiobutton behavior

Make a new class Form2, paste this over it:

public partial class Form2 : Form
{
private int index = 0; //helper to track the selected index
public Form2()
{
InitializeComponent();
checkedListBox1.SetItemChecked(0, true); //check at least one item
}

//this fires before an item is checked. Really, Microsoft should perhaps have called it ItemCheckChanging
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (index == -1) //programmatic change, exit early; see below
return;
else if (index == e.Index)
e.NewValue = CheckState.Checked; //undo an attempt to uncheck the checked item
else
{
var oldIndex = index; //what item do we want to uncheck
index = -1; //prevent event handler firing again when we..
checkedListBox1.SetItemChecked(oldIndex, false); //..uncheck th old
index = e.Index; //track the newly checked
}
}
}

By the way, your life might be simpler if you use a datagridview bound to a table with 2 columns, a bool and a text..

How do I group Windows Form radio buttons?

Put all radio buttons for a group in a container object like a Panel or a GroupBox. That will automatically group them together in Windows Forms.

Dynamic creating radiobuttons and arange them inside form

If you want to fix your code without the suggested ways in the comments

private void CreateRadioButton()
{
int rbCount = 40;
int numberOfColumns = 8;
var radioButtons = new RadioButton[rbCount];
int y = 20;
for (int i = 0; i < rbCount; ++i)
{
radioButtons[i] = new RadioButton();
radioButtons[i].Text = Convert.ToString(i);
if (i%numberOfColumns==0) y += 20;
var x = 514 + i%numberOfColumns * 37;
radioButtons[i].Location = new Point(x, y);
radioButtons[i].Size = new Size(37, 17);
this.Controls.Add(radioButtons[i]);
}
}


Related Topics



Leave a reply



Submit