该组中哪个单选按钮被选中?

132

使用WinForms;有没有更好的方法来查找群组中选中的RadioButton?我认为下面的代码不应该是必要的。当您选择不同的RadioButton时,它知道应取消哪一个……因此它应该知道哪个已被选中。如何在不进行大量if语句(或switch)的情况下获取该信息。

     RadioButton rb = null;

     if (m_RadioButton1.Checked == true)
     {
        rb = m_RadioButton1;
     }
     else if (m_RadioButton2.Checked == true)
     {
        rb = m_RadioButton2;
     }
     else if (m_RadioButton3.Checked == true)
     {
        rb = m_RadioButton3;
     }

1
底层代码不知道要取消哪个,它只会迭代更改的控件同一级别父控件下面的所有RadioButton控件,并取消选中以前选定的那个。 - João Angelo
1
你是在使用WinForms还是ASP.Net? - SLaks
14个回答

241

你可以使用 LINQ:

var checkedButton = container.Controls.OfType<RadioButton>()
                                      .FirstOrDefault(r => r.Checked);
请注意,这要求所有单选按钮直接放置在同一个容器中(例如,面板或表单),并且容器中只有一个组。如果不是这种情况,您可以在构造函数中为每个组创建List<RadioButton>,然后编写list.FirstOrDefault(r => r.Checked)

在你的回答的第二段中,应该是s.FirstOrDefault而不是list.FirstOrDefault吗? - user212218
@Phoenix:s是复数形式,不是变量名。 - SLaks
非常好的回答,但并没有真正回答 OP 的主要问题。请看我的回答。 - D'Hag
对于使用vb.net的各位,我将为您节省去Telerik转换器的麻烦:Dim checkedButton = radConnections.Controls.OfType(Of RadioButton)().FirstOrDefault(Function(r) r.Checked) - JoshYates1980
感谢您分享您的精彩知识。 - Erdinç

42

您可以将所有按钮的CheckedEvents连接到一个处理程序。在那里,您可以轻松地获取正确的复选框。

// Wire all events into this.
private void AllCheckBoxes_CheckedChanged(Object sender, EventArgs e) {
    // Check of the raiser of the event is a checked Checkbox.
    // Of course we also need to to cast it first.
    if (((RadioButton)sender).Checked) {
        // This is the correct control.
        RadioButton rb = (RadioButton)sender;
    }
}

应该改为 - if (((RadioButton)sender).Checked) - Frank Tzanabetis
1
WPF的RadioButton中没有CheckedChanged事件,你从哪里得到它的? - Murhaf Sousli

27

对于那些没有使用 LINQ 的人:

RadioButton GetCheckedRadio(Control container)
{
    foreach (var control in container.Controls)
    {
        RadioButton radio = control as RadioButton;

        if (radio != null && radio.Checked)
        {
            return radio;
        }
    }

    return null;
}

14

OP希望通过组获得已选中的RadioButton。虽然@SLaks的答案非常好,但它实际上并没有回答OP的主要问题。为了改进@SLaks的答案,只需将LINQ再进一步。

以下是我自己工作代码中的示例。与普通的WPF一样,我的RadioButton包含在一个名为“myGrid”的Grid中,还有其他类型的控件。我在Grid中有两个不同的RadioButton组。

要从特定组中获取已选中的RadioButton:

List<RadioButton> radioButtons = myGrid.Children.OfType<RadioButton>().ToList();
RadioButton rbTarget = radioButtons
      .Where(r => r.GroupName == "GroupName" && r.IsChecked)
      .Single();
如果你的代码可能存在没有选中任何单选按钮的情况,那么请使用SingleOrDefault()(如果我不使用三态按钮,则我总是将一个按钮“IsChecked”作为默认选择)。

如果您的代码可能出现无单选按钮被选中的情况,则使用 SingleOrDefault()(如果我不使用三态按钮,则我总是将一个按钮“IsChecked”设置为默认选择。)


1
r.GroupName == "GroupName" 和 r.IsChecked 是不同的类型(bool 和 bool?),你应该使用 r.IsChecked.Value,它是 bool 类型。 - Mike
1
尝试使用.Where(r => r.GroupName == "GroupName" && r.IsChecked == true),因为r.IsChecked是可空布尔属性。 - Firnas
这里的myGrid是指什么? - Unnikrishnan
@Mike,请问这里的“radioButtons”是指什么? - Bella Swan
1
@BellaSwan - 看一下代码 - 你需要创建一个包含所有单选按钮的列表并将其分配给一个变量。然后,在同一个变量上运行 Where 选择并将其分配给 rbTarget。 - Mike
显示剩余3条评论

5
你可以使用 CheckedChanged 事件来控制所有单选按钮。 Sender 将是未选中和选中的单选按钮。

2
有时候在这种情况下,我会怀念我的青春岁月,当时Access是我的首选工具,我可以给单选按钮组中的每个单选按钮设置自己的值。
在C#中,我的方法是使用标签来设置值,当我从组中选择一个选项时,我读取所选单选按钮的标签值。在这个例子中,directionGroup 是一个包含四个五个单选按钮的组,其中其他四个单选按钮的标签分别为 "None" 和 "NE"、"SE"、"NW" 和 "SW"。
我主动使用一个按钮来捕获所选按钮的值,因为将一个事件处理程序分配给所有按钮的CHeckCHanged事件会导致每个按钮都触发,因为改变一个按钮会改变它们所有的按钮。所以 sender 的值始终是组中的第一个 RadioButton。相反,当我需要找出选中的是哪一个,并且我想要检索每个 RadioButton 的 Tag 属性中的值时,我使用这种方法。
  private void ShowSelectedRadioButton()
    {
        List<RadioButton> buttons = new List<RadioButton>();
        string selectedTag = "No selection";
        foreach (Control c in directionGroup.Controls)
        {
            if (c.GetType() == typeof(RadioButton))
            {
                buttons.Add((RadioButton)c);
            }
        }
        var selectedRb = (from rb in buttons where rb.Checked == true select rb).FirstOrDefault();
        if (selectedRb!=null)
        {
             selectedTag = selectedRb.Tag.ToString();
        }

        FormattableString result = $"Selected Radio button tag ={selectedTag}";
        MessageBox.Show(result.ToString());
    }

顺便提一下,我已经在工作中测试并使用过这个。

乔伊


仅修改“FormatableString”结果,我就能在我的程序中使用这段代码。我之前也不知道radioButton标签。这就是答案应该的样子。非常感谢。 - Unnikrishnan

1

处理这个问题的简单方法是捕获每个单选按钮的CheckedChanged事件,并让每个单选按钮将其值设置在其容器的标记字段中。然后,当您准备读取哪个单选按钮被点击时,只需使用容器的标记字段即可。

    private void rbUnread_CheckedChanged(object sender, EventArgs e)
    {
        if (rbUnread.Checked)
            pnlStatus.Tag = 1;
    }
    private void rbRead_CheckedChanged(object sender, EventArgs e)
    {
        if (rbRead.Checked)
            pnlStatus.Tag = 2;
    }
    private void rbUnfinished_CheckedChanged(object sender, EventArgs e)
    {
        if (rbUnfinished.Checked)
            pnlStatus.Tag = 3;
    }

1
您可以使用扩展方法来迭代 RadioButton 的 Parent.Controls 集合。这样可以查询同一范围内的其他 RadioButton。使用两个扩展方法,您可以使用第一个确定组中是否选择了任何 RadioButton,然后使用第二个获取选择。RadioButton 标记字段可用于保存枚举以标识组中的每个 RadioButton:
    public static int GetRadioSelection(this RadioButton rb, int Default = -1) {
        foreach(Control c in  rb.Parent.Controls) {
            RadioButton r = c as RadioButton;
            if(r != null && r.Checked) return Int32.Parse((string)r.Tag);
        }
        return Default;
    }

    public static bool IsRadioSelected(this RadioButton rb) {
        foreach(Control c in  rb.Parent.Controls) {
            RadioButton r = c as RadioButton;
            if(r != null && r.Checked) return true;
        }
        return false;
    }

这是一个典型的使用模式:

if(!MyRadioButton.IsRadioSelected()) {
   MessageBox.Show("No radio selected.");
   return;
}
int selection = MyRadioButton.GetRadioSelection;

1
除了使用CheckedChangedEvent来连接之外,您还可以使用控件的“Tag”属性来区分单选按钮...一个(意大利面代码)的替代方法是“TabIndex”属性;P

它意味着您可以在所选的单选按钮ID上快速使用switch-case(使用属性System.Windows.Forms.Control.Tag),请不要因为您不理解我对问题的补充而将其评价降低。 - Binkan Salaryman

0
如果你想将选择保存到文件或其他地方并在以后调用它,这是我所做的:
string[] lines = new string[1];

lines[0]  = groupBoxTes.Controls.OfType<RadioButton>()
            .FirstOrDefault(r => r.Checked).Text;

File.WriteAllLines("Config.ini", lines);

然后使用以下方式调用

string[] ini = File.ReadAllLines("Config.ini");
groupBoxTes.Controls.OfType<RadioButton>()
.FirstOrDefault(r => (r.Text == ini[0])).Checked = true;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接