WinForms RadioButtonList doesn't exist?
Asked Answered
H

3

11

I know that WebForms has a RadioButtonList control, but I can't find one for WinForms. What I need is to have 3 RadioButtons grouped together, so that only 1 can be selected at a time. I'm finding that I have to do this through code, which is a pain. Am I just not seeing RadioButtonList somewhere, or does it really not exist in WinForms?

Heathcote answered 18/6, 2009 at 21:55 Comment(0)
Z
8

Apparently not.

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

Zima answered 18/6, 2009 at 21:58 Comment(2)
Weird, I was grouping them in a GroupBox but I thought it wasn't working. Thank you!Heathcote
Yes, but you lose the function of the RadioButtonList Value property and it's data binding potential.Hainaut
E
22

If you just want to group radio buttons, it's enough to put them in a container, then they will act like a group, but if you need data-binding like how a ComboBox or ListBox or CheckedListBox works, you need a RadioButtonList control.

Windows forms doesn't have a built-in RadioButtonList control. You can create your own control by deriving form ListBox and making it owner-draw and draw radio buttons yourself. This is the way which CheckedListBox is created as well.

This way, the control supports data-binding and will benefit from all features of ListBox, including DataSource, SelectedValue, DisplayMember, ValueMember and so on. For example you can simply use it this way:

this.radioButtonList1.DataSource = peopleTable; 
this.radioButtonList1.DisplayMember = "Name"; 
this.radioButtonList1.ValueMember= "Id";

Or for example for an enum, simply this way:

this.radioButtonList1.DataSource = Enum.GetValues(typeof(DayOfWeek)); 

In below image, the second RadioButtonList is disabled by setting Enabled = false;:

enter image description here enter image description here

Also the control supports right to left as well:

enter image description here

It also supports multi column:

enter image description here

RadioButtonList

Here is the source code for control. You can use it like a normal ListBox by adding items or setting data source with/without using data-binding:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
public class RadioButtonList : ListBox
{
    Size s;
    public RadioButtonList()
    {
        this.DrawMode = DrawMode.OwnerDrawFixed;
        using (var g = Graphics.FromHwnd(IntPtr.Zero))
            s = RadioButtonRenderer.GetGlyphSize(
                Graphics.FromHwnd(IntPtr.Zero), RadioButtonState.CheckedNormal);
    }
    protected override void OnDrawItem(DrawItemEventArgs e)
    {

        var text = (Items.Count > 0) ? GetItemText(Items[e.Index]) : Name;
        Rectangle r = e.Bounds; Point p;
        var flags = TextFormatFlags.Default | TextFormatFlags.NoPrefix;
        var selected = (e.State & DrawItemState.Selected) == DrawItemState.Selected;
        var state = selected ?
            (Enabled ? RadioButtonState.CheckedNormal : 
                       RadioButtonState.CheckedDisabled) :
            (Enabled ? RadioButtonState.UncheckedNormal : 
                       RadioButtonState.UncheckedDisabled);
        if (RightToLeft == System.Windows.Forms.RightToLeft.Yes)
        {
            p = new Point(r.Right - r.Height + (ItemHeight - s.Width) / 2,
                r.Top + (ItemHeight - s.Height) / 2);
            r = new Rectangle(r.Left, r.Top, r.Width - r.Height, r.Height);
            flags |= TextFormatFlags.RightToLeft | TextFormatFlags.Right;
        }
        else
        {
            p = new Point(r.Left + (ItemHeight - s.Width) / 2,
            r.Top + (ItemHeight - s.Height) / 2);
            r = new Rectangle(r.Left + r.Height, r.Top, r.Width - r.Height, r.Height);
        }
        var bc = selected ? (Enabled ? SystemColors.Highlight : 
            SystemColors.InactiveBorder) : BackColor;
        var fc = selected ? (Enabled ? SystemColors.HighlightText : 
            SystemColors.GrayText) : ForeColor;
        using (var b = new SolidBrush(bc))
            e.Graphics.FillRectangle(b, e.Bounds);
        RadioButtonRenderer.DrawRadioButton(e.Graphics, p, state);
        TextRenderer.DrawText(e.Graphics, text, Font, r, fc, bc, flags);
        e.DrawFocusRectangle();
        base.OnDrawItem(e);
    }
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public override SelectionMode SelectionMode
    {
        get { return System.Windows.Forms.SelectionMode.One; }
        set { }
    }
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public override int ItemHeight
    {
        get { return (this.Font.Height + 2); }
        set { }
    }
    [EditorBrowsable(EditorBrowsableState.Never), Browsable(false),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public override DrawMode DrawMode
    {
        get { return base.DrawMode; }
        set { base.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; }
    }
}
Exotic answered 28/12, 2016 at 4:37 Comment(0)
Z
8

Apparently not.

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

Zima answered 18/6, 2009 at 21:58 Comment(2)
Weird, I was grouping them in a GroupBox but I thought it wasn't working. Thank you!Heathcote
Yes, but you lose the function of the RadioButtonList Value property and it's data binding potential.Hainaut
C
4

The simple fact that several radio buttons are in the same container makes them mutually exclusive, you don't have to code this behavior yourself. Just put them in a Panel or GroupBox as suggested by Matthew

Chatterer answered 18/6, 2009 at 22:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.