One generic work-around is a to use a listbox styled as radio buttons to prevent having to use multiple bindings/controls/checking on checked. There's only one control which event needs to be monitored (SelectedIndexChanged
) and instead of checking which radiobutton is checked there's SelectedItem
. Another advantage is the ability to bind datasources instead of dynamically adding radiobuttons.
For that purpose, here's a simple RadioButtonBox
control that does just that (made it a long time ago and haven't revised it since, but still use it regularly)
public class RadioButtonBox:ListBox
{
public readonly RadioButtonBoxPainter Painter;
public RadioButtonBox()
{
Painter = new RadioButtonBoxPainter(this);
}
[DefaultValue(DrawMode.OwnerDrawFixed)]
public override DrawMode DrawMode
{
get{return base.DrawMode;}
set{base.DrawMode = value;}
}
}
public class RadioButtonBoxPainter : IDisposable
{
public readonly ListBox ListBox;
public RadioButtonBoxPainter(ListBox ListBox)
{
this.ListBox = ListBox;
ListBox.DrawMode = DrawMode.OwnerDrawFixed;
ListBox.DrawItem += ListBox_DrawItem;
}
void ListBox_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index == -1) return;
Rectangle r = e.Bounds;
r.Width = r.Height;
bool selected = (e.State & DrawItemState.Selected) > 0;
e.DrawBackground();
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
ControlPaint.DrawRadioButton(e.Graphics, r, selected ? ButtonState.Checked : ButtonState.Normal);
r.X = r.Right + 2;
r.Width = e.Bounds.Width - r.X;
string txt;
if (ListBox.Site != null && ListBox.Site.DesignMode && e.Index >= ListBox.Items.Count)
txt = ListBox.Name;
else
txt = ListBox.GetItemText(ListBox.Items[e.Index]);
using (var b = new SolidBrush(e.ForeColor))
e.Graphics.DrawString(txt, e.Font, b, r);
if (selected)
{
r = e.Bounds;
r.Width--; r.Height--;
e.Graphics.DrawRectangle(Pens.DarkBlue, r);
}
}
public void Dispose()
{
ListBox.DrawItem -= ListBox_DrawItem;
}
}
The RadioButtonBox
is the control, RadioButtonBoxPainter
is the class that does the custom painting and can be used on any ListBox (the painting can be integrated into the control as well, but at the start this was made to give some existing listboxes a radiobutton look).
As for the display, normally it would still have that listbox feel:

But by setting backcolor to 'Control' and no borderstyle, the result looks like regular radiobuttons:

If the second layout is always preferred, they can always be set as defaults in the RadioButtonBox control.