简体   繁体   English

选中组中的哪个单选按钮?

[英]Which Radio button in the group is checked?

Using WinForms;使用窗体; Is there a better way to find the checked RadioButton for a group?有没有更好的方法来为一个组找到选中的 RadioButton? It seems to me that the code below should not be necessary.在我看来,下面的代码应该不是必需的。 When you check a different RadioButton then it knows which one to uncheck… so it should know which is checked.当您选中一个不同的 RadioButton 时,它知道要取消选中哪个……所以它应该知道选中了哪个。 How do I pull that information without doing a lot of if statements (or a switch).如何在不执行大量 if 语句(或开关)的情况下提取该信息。

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

You could use LINQ:你可以使用 LINQ:

var checkedButton = container.Controls.OfType<RadioButton>()
                                      .FirstOrDefault(r => r.Checked);

Note that this requires that all of the radio buttons be directly in the same container (eg, Panel or Form), and that there is only one group in the container.请注意,这要求所有单选按钮都直接位于同一个容器(例如,面板或表单)中,并且容器中只有一组。 If that is not the case, you could make List<RadioButton> s in your constructor for each group, then write list.FirstOrDefault(r => r.Checked) .如果不是这种情况,您可以在构造函数中为每个组创建List<RadioButton> ,然后编写list.FirstOrDefault(r => r.Checked)

You can wire the CheckedEvents of all the buttons against one handler.您可以针对一个处理程序连接所有按钮的CheckedEvents There you can easily get the correct Checkbox.在那里您可以轻松获得正确的复选框。

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

For those without LINQ:对于那些没有 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;
}

The OP wanted to get the checked RadioButton BY GROUP. OP 希望按组获得选中的 RadioButton。 While @SLaks' answer is excellent, it doesn't really answer the OP's main question.虽然@SLaks 的回答非常好,但它并没有真正回答 OP 的主要问题。 To improve on @SLaks' answer, just take the LINQ one step further.要改进@SLaks 的回答,只需将 LINQ 更进一步。

Here's an example from my own working code.这是我自己的工作代码中的一个示例。 Per normal WPF, my RadioButtons are contained in a Grid (named "myGrid") with a bunch of other types of controls.对于普通的 WPF,我的 RadioButtons 包含在带有一堆其他类型控件的Grid (名为“myGrid”)中。 I have two different RadioButton groups in the Grid.我在网格中有两个不同的 RadioButton 组。

To get the checked RadioButton from a particular group:要从特定组中获取选中的 RadioButton:

List<RadioButton> radioButtons = myGrid.Children.OfType<RadioButton>().ToList();
RadioButton rbTarget = radioButtons
      .Where(r => r.GroupName == "GroupName" && r.IsChecked)
      .Single();

If your code has the possibility of no RadioButtons being checked, then use SingleOrDefault() (If I'm not using tri-state buttons, then I always set one button "IsChecked" as a default selection.)如果你的代码有可能没有选中 RadioButtons,那么使用SingleOrDefault() (如果我不使用三态按钮,那么我总是将一个按钮“IsChecked”设置为默认选择。)

You can use the CheckedChanged event for all your RadioButtons.您可以对所有 RadioButton 使用CheckedChanged事件。 Sender will be the unchecked and checked RadioButtons. Sender将是未选中和选中的 RadioButton。

Sometimes in situations like this I miss my youth, when Access was my poison of choice, and I could give each radio button in a group its own value.有时在这种情况下,我会怀念我的青春,那时 Access 是我的毒药,我可以为组中的每个单选按钮赋予自己的价值。

My hack in C# is to use the tag to set the value, and when I make a selection from the group, I read the value of the tag of the selected radiobutton.我在 C# 中的技巧是使用标签来设置值,当我从组中进行选择时,我会读取所选单选按钮的标签值。 In this example, directionGroup is the group in which I have four five radio buttons with "None" and "NE", "SE", "NW" and "SW" as the tags on the other four radiobuttons.在这个例子中, directionGroup是我有四个五个单选按钮的组,其中“None”和“NE”、“SE”、“NW”和“SW”作为其他四个单选按钮上的标签。

I proactively used a button to capture the value of the checked button, because because assigning one event handler to all of the buttons' CHeckCHanged event causes EACH button to fire, because changing one changes them all.我主动使用一个按钮来捕获选中按钮的值,因为将一个事件处理程序分配给所有按钮的 CHeckCHanged 事件会导致每个按钮触发,因为更改一个会更改所有按钮。 So the value of sender is always the first RadioButton in the group.所以 sender 的值始终是组中的第一个 RadioButton。 Instead, I use this method when I need to find out which one is selected, with the values I want to retrieve in the Tag property of each 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());
    }

FYI, I have tested and used this in my work.仅供参考,我已经在我的工作中测试并使用了它。

Joey乔伊

You can use an Extension method to iterate the RadioButton's Parent.Controls collection.您可以使用扩展方法来迭代 RadioButton 的 Parent.Controls 集合。 This allows you to query other RadioButtons in the same scope.这允许您查询同一范围内的其他 RadioButton。 Using two extension methods, you can use the first determine whether any RadioButtons in the group are selected, then use the second to get the selection.使用两种扩展方法,您可以使用第一种来确定是否选择了组中的任何 RadioButton,然后使用第二种来获取选择。 The RadioButton Tag field can be used to hold an Enum to identify each RadioButton in the group: RadioButton Tag 字段可用于保存 Enum 以标识组中的每个 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;
    }

Here's a typical use pattern:这是一个典型的使用模式:

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

除了 CheckedChangedEvent 接线之外,还可以使用 Controls“Tag”属性来区分单选按钮......(意大利面条代码)替代方法是“TabIndex”属性;P

if you want to save the selection to file or any else and call it later, here what I do如果您想将选择保存到文件或任何其他文件并稍后调用,请执行以下操作

string[] lines = new string[1];

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

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

then call it with然后用

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

If you want to get the index of the selected radio button inside a control you can use this method:如果要获取控件内所选单选按钮的索引,可以使用以下方法:

public static int getCheckedRadioButton(Control c)
{
    int i;
    try
    {
        Control.ControlCollection cc = c.Controls;
        for (i = 0; i < cc.Count; i++)
        {
            RadioButton rb = cc[i] as RadioButton;
            if (rb.Checked)
            {
                return i;
            }
        }
    }
    catch
    {
        i = -1;
    }
    return i;
}

Example use:使用示例:

int index = getCheckedRadioButton(panel1);

The code isn't that well tested, but it seems the index order is from left to right and from top to bottom, as when reading a text.代码没有经过很好的测试,但似乎索引顺序是从左到右和从上到下,就像阅读文本时一样。 If no radio button is found, the method returns -1.如果未找到单选按钮,则该方法返回 -1。

Update: It turned out my first attempt didn't work if there's no radio button inside the control.更新:事实证明,如果控件内没有单选按钮,我的第一次尝试将不起作用。 I added a try and catch block to fix that, and the method now seems to work.我添加了一个 try 和 catch 块来解决这个问题,现在该方法似乎有效。

The GroupBox has a Validated event for this purpose, if you are using WinForms.如果您使用的是 WinForms,则 GroupBox 具有用于此目的的 Validated 事件。

private void grpBox_Validated(object sender, EventArgs e)
    {
        GroupBox g = sender as GroupBox;
        var a = from RadioButton r in g.Controls
                 where r.Checked == true select r.Name;
        strChecked = a.First();
     }

For developers using VB.NET对于使用 VB.NET 的开发人员


Private Function GetCheckedRadio(container) As RadioButton
    For Each control In container.Children
        Dim radio As RadioButton = TryCast(control, RadioButton)

        If radio IsNot Nothing AndAlso radio.IsChecked Then
            Return radio
        End If
    Next

    Return Nothing
End Function

Yet another try - Using event lambda expressions另一个尝试 - 使用事件 lambda 表达式

As form initializes a single event handler can be assigned to all controls of type RadioButton in a group box, and use .tabIndex or .tag property to identify what option is checked when it changes.在表单初始化时,可以将单个事件处理程序分配给组框中RadioButton类型的所有控件,并使用 .tabIndex 或 .tag 属性来标识更改时选中的选项。

This way you can subscribe to any of the events of each radio button in one go通过这种方式,您可以一次性订阅每个单选按钮的任何事件

int priceOption = 0;
foreach (RadioButton rbtn in grp_PriceOpt.Controls.OfType<RadioButton>())
{
    rbtn.CheckedChanged += (o, e) =>
    {
        var button = (RadioButton)o;
        if (button.Checked)
        {
            priceOption = button.TabIndex;
        }
    };
}

As events are assigned to radio buttons only, no type checking of sender is implemented.由于事件仅分配给单选按钮,因此没有实现发送者的类型检查。

Also notice as we loop all buttons this could be a perfect moment to assign data properties, change text etc.还要注意,当我们循环所有按钮时,这可能是分配数据属性、更改文本等的完美时机。

A simple way to handle this is to capture the CheckedChanged event for each of the radio buttons and have each one set their value in the Tag field of their container.处理此问题的一种简单方法是为每个单选按钮捕获 CheckedChanged 事件,并让每个单选按钮在其容器的 Tag 字段中设置它们的值。 Then when you're ready to read which radio button is clicked, just use the Tag field of the container.然后,当您准备好阅读单击了哪个单选按钮时,只需使用容器的 Tag 字段即可。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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