Какой переключатель в группе отмечен?


118

Использование WinForms; Есть ли лучший способ найти отмеченный RadioButton для группы? Мне кажется, что приведенный ниже код не нужен. Когда вы выбираете другой RadioButton, он знает, какой из них нужно снять… поэтому он должен знать, какой из них отмечен. Как получить эту информацию, не выполняя много инструкций 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;
     }

1
Базовый код не знает, какой из них нужно снять, он просто выполняет итерацию всех элементов управления RadioButton, находящихся ниже того же родителя измененного элемента управления, и снимает отметку с того, который был ранее отмечен.
Жуан Анджело,

1
Вы используете WinForms или ASP.Net?
SLaks

Ответы:


219

Вы можете использовать LINQ:

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

Обратите внимание, что для этого необходимо, чтобы все переключатели находились непосредственно в одном контейнере (например, в панели или форме) и чтобы в контейнере была только одна группа. Если это не так, вы можете создать List<RadioButton>s в своем конструкторе для каждой группы, а затем написать list.FirstOrDefault(r => r.Checked).


Должно ли это быть s.FirstOrDefaultвместо list.FirstOrDefaultвторого абзаца вашего ответа?

@Phoenix: sэто множественное число, а не имя переменной.
SLaks

Отличный ответ, но на самом деле не ответил на главный вопрос OP. Смотрите мой ответ.
D'Hag

для вас, ребята, vb.net, я сэкономлю вам поездку в конвертер Telerik: Dim checkedButton = radConnections.Controls.OfType (Of RadioButton) (). FirstOrDefault (Function (r) r.Checked)
JoshYates1980,

36

Вы можете связать 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)
Фрэнк Цанабетис

1
В WPF RadioButton нет CheckedChanged, откуда вы его взяли?
Мурхаф Сусли

26

Для тех, у кого нет 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;
}

12

OP хотел получить проверенный RadioButton BY GROUP. Хотя ответ @SLaks отличный, он на самом деле не отвечает на главный вопрос OP. Чтобы улучшить ответ @SLaks, просто сделайте LINQ еще дальше.

Вот пример из моего собственного рабочего кода. В обычном WPF мои RadioButtons содержатся в Grid(названном "myGrid") с множеством других типов элементов управления. У меня есть две разные группы RadioButton в сетке.

Чтобы получить проверенный RadioButton из определенной группы:

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

Если в вашем коде есть возможность не проверять RadioButtons, используйте SingleOrDefault()(Если я не использую кнопки с тремя состояниями, я всегда устанавливаю одну кнопку «IsChecked» как выбор по умолчанию.)


1
r.GroupName == "GroupName" и r.IsChecked относятся к разным типам (bool и bool?), вы должны были использовать r.IsChecked.Value, имеющий тип bool.
Майк

1
попробуйте, .Where(r => r.GroupName == "GroupName" && r.IsChecked == true)потому что r.IsCheckedсвойство bool допускает значение NULL.
Фирнас

на что здесь ссылается myGrid.
Унникришнан

@Mike Не могли бы вы сказать, что здесь "radioButtons"?
Белла Свон,

1
@BellaSwan - взгляните на код - вы создаете список всех переключателей и назначаете его переменной. Затем для той же переменной вам нужно запустить выбор Where и назначить его rbTarget.
Майк,

5

Вы можете использовать событие CheckedChanged для всех ваших RadioButton. Senderбудут отключены и отмечены RadioButtons.


1

Вы можете использовать метод Extension для итерации коллекции RadioButton Parent.Controls. Это позволяет вам запрашивать другие RadioButton в той же области. Используя два метода расширения, вы можете использовать первый, чтобы определить, выбраны ли какие-либо RadioButton в группе, а затем использовать второй, чтобы получить выбор. Поле 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;
    }

Вот типичный образец использования:

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

1

В дополнение к подключению CheckedChangedEvent можно использовать свойство Controls "Tag", чтобы различать переключатели ... альтернативой (спагетти-код) будет свойство "TabIndex"; P


это означает, что вы можете быстро использовать switch-case для выбранного идентификатора радиокнопки (используя свойство System.Windows.Forms.Control.Tag), пожалуйста, не понижайте оценку, если вы просто не понимаете мое добавление к вопросу.
Binkan Salaryman 05

1

Иногда в подобных ситуациях я скучаю по своей юности, когда Access был моим любимым ядом, и я мог дать каждому переключателю в группе свое собственное значение.

Мой хакер в C # заключается в использовании тега для установки значения, и когда я делаю выбор из группы, я читаю значение тега выбранного радиокнопки. В этом примере directionGroup - это группа, в которой у меня есть четыре пяти переключателя с «None» и «NE», «SE», «NW» и «SW» в качестве тегов на других четырех переключателях.

Я проактивно использовал кнопку, чтобы зафиксировать значение отмеченной кнопки, потому что назначение одного обработчика событий событию CHeckCHanged для всех кнопок приводит к срабатыванию КАЖДОЙ кнопки, потому что изменение одной кнопки меняет их все. Таким образом, значение отправителя всегда является первым RadioButton в группе. Вместо этого я использую этот метод, когда мне нужно выяснить, какой из них выбран, со значениями, которые я хочу получить в свойстве Tag каждого RadioButton.

  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. Вот какими должны быть ответы. Великий сэр.
Унникришнан

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;

0

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

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

Пример использования:

int index = getCheckedRadioButton(panel1);

Код не так хорошо протестирован, но кажется, что порядок индекса слева направо и сверху вниз, как при чтении текста. Если переключатель не найден, метод возвращает -1.

Обновление: оказалось, что моя первая попытка не сработала, если внутри элемента управления нет переключателя. Я добавил блок try and catch, чтобы исправить это, и теперь этот метод работает.


0

GroupBox имеет для этой цели событие Validated, если вы используете WinForms.

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

0

Для разработчиков, использующих 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.