简体   繁体   中英

Grouping Windows Forms Radiobuttons with different parent controls in C#

I've got a Windows Forms application in which I have a number of RadioButtons. These RadioButtons are placed within a FlowLayoutPanel which automatically arranges them for me. All RadioButtons that are directly added to the FlowLayoutPanel are grouped, meaning I can select only one of them. However, some of these RadioButtons are paired up with a TextBox so I can supply some argument there. But to have all this arranged properly, I add a Panel control to the FlowLayoutPanel so I can control the alignment of the RadioButton and TextBox relatively to each other myself.

These RadioButtons now have their own respective Panels as parent controls and thus are no longer included in the radio group with the other RadioButtons. I read that the the RadioButtons that are in the System.Web.UI namespace have a GroupName property, but unfortunately their System.Windows.Forms counterparts lack this property. Is there some other way I can group these radio buttons are am I going to have to handle onClick events myself?

Thanks, Jerry

I'm afraid you'll have to handle this manually... It's not so bad actually, you can probably just store all the RadioButton in a list, and use a single event handler for all of them:

private List<RadioButton> _radioButtonGroup = new List<RadioButton>();
private void radioButton_CheckedChanged(object sender, EventArgs e)
{
    RadioButton rb = (RadioButton)sender;
    if (rb.Checked)
    {
        foreach(RadioButton other in _radioButtonGroup)
        {
            if (other == rb)
            {
                continue;
            }
            other.Checked = false;
        }
    }
}

I agree with @JonH - using tags is the cleanest way to do that (imho)

  private void FormLoad(object sender, EventArgs e)
  {
     radioCsv.Tag = DataTargetTypes.CsvFile;
     radioTabbed.Tag = DataTargetTypes.TxtFile;
     radioSas.Tag = DataTargetTypes.SasFile;
  }

  private void RadioButtonCheckedChanged(object sender, EventArgs e)
  {
     var radio = (RadioButton) sender;
     this.DataDestinationType = (DataTargetTypes)radio.Tag;
  }

Here is a little improvement over the first answer: create a RadioGroup class that encapsulates the grouping functionality and adds support for standard keyboard navigation (up/down keys) and makes tabbing work.

To use it, simply declare a RadioGroup member in your form and new it (after InitializeComponent()), passing all the radio buttons you want in the group in proper order.

public class RadioGroup
{
    List<RadioButton> _radioButtons;

    public RadioGroup(params RadioButton[] radioButtons)
    {
        _radioButtons = new List<RadioButton>(radioButtons);
        foreach (RadioButton radioButton in _radioButtons)
        {
            radioButton.TabStop = false;
            radioButton.KeyUp += new KeyEventHandler(radioButton_KeyUp);
            radioButton.CheckedChanged += new EventHandler(radioButton_CheckedChanged);
        }
        _radioButtons[0].TabStop = true;
    }

    void radioButton_KeyUp(object sender, KeyEventArgs e)
    {
        e.Handled = true;
        RadioButton radioButton = (RadioButton)sender;
        int index = _radioButtons.IndexOf(radioButton);

        if (e.KeyCode == Keys.Down)
        {
            index++;
            if (index >= _radioButtons.Count)
            {
                index = 0;
            }
            e.Handled = true;
        }
        else if (e.KeyCode == Keys.Up)
        {
            index--;
            if (index < 0)
            {
                index = _radioButtons.Count - 1;
            }
            e.Handled = true;
        }

        radioButton = _radioButtons[index];
        radioButton.Focus();
        radioButton.Select();
    }

    void radioButton_CheckedChanged(object sender, EventArgs e)
    {
        RadioButton currentRadioButton = (RadioButton)sender;

        if (currentRadioButton.Checked)
        {
            foreach (RadioButton radioButton in _radioButtons)
            {
                if (!radioButton.Equals(currentRadioButton))
                {
                    radioButton.Checked = false;
                }
            }
        }
    }
}

One caveat: the up/down keys won't work well with the existing RadioButton class because it already handles the up/down keys. One easy way to fix it to subclass RadioButton and turn off handling of up/down keys:

public class RadioButtonEx : RadioButton
{
    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if (keyData == Keys.Up || keyData == Keys.Down)
        {
            return true;
        }

        return base.ProcessCmdKey(ref msg, keyData);
    }
}

@Jerry, I'm not too familiar with Windows Forms, but I will take a shot. If there a property called Tag , you could tag each radio button with a unique tag.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM