WinForms RadioButtonList не существует?

Я знаю, что WebForms имеет элемент управления RadioButtonList, но я не могу найти его для WinForms. Мне нужно иметь 3 RadioButtons, сгруппированных вместе, так что только один может быть выбран за один раз. Я нахожу, что мне нужно сделать это с помощью кода, что является болью. Я просто не вижу RadioButtonList где-то, или он действительно не существует в WinForms?

Ответ 2

Если вы просто хотите сгруппировать переключатели, достаточно поместить их в контейнер, тогда они будут действовать как группа, но если вам нужно привязать данные, например, как ComboBox или ListBox или CheckedListBox работает, вам нужен элемент управления RadioButtonList.

Формы Windows не имеют встроенного элемента управления RadioButtonList. Вы можете создать свой собственный элемент управления, извлекая форму ListBox и заставляя ее рисовать владельца и рисовать переключатели самостоятельно. Именно так и создается CheckedListBox.

Таким образом, элемент управления поддерживает привязку данных и использует все функции ListBox, включая DataSource, SelectedValue, DisplayMember, ValueMember и так далее. Например, вы можете просто использовать его следующим образом:

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

Или, например, для enum, просто так:

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

На изображении ниже второе RadioButtonList отключается установкой Enabled = false;:

enter image description here enter image description here

Также элемент управления поддерживает справа налево:

enter image description here

Он также поддерживает несколько столбцов:

enter image description here

RadioButtonList

Вот исходный код для контроля. Вы можете использовать его как обычный ListBox, добавляя элементы или устанавливая источник данных с/без привязки данных:

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; }
    }
}

Ответ 3

Простой факт, что несколько переключателей находятся в одном контейнере, делает их взаимоисключающими, вам не нужно вводить это поведение самостоятельно. Просто поместите их в Panel или GroupBox, как предложено Мэтью