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



использование 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;
}
943   12  

12 ответов:

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

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

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

вы можете связать 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;
    }
}

для тех, кто без 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;
}

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

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

чтобы получить проверенный Радиобуттон из a конкретная группа:

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

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

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

Вы можете использовать метод расширения, чтобы выполнить итерации родительского компонента 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;

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

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

Я активно использовал кнопку для захвата значения проверенной кнопки, потому что, поскольку назначение одного обработчика событий для всех событий CHeckCHanged кнопок приводит к срабатыванию каждой кнопки, потому что изменение одного изменяет их все. Таким образом, значение sender всегда является первым 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());
    }

к вашему сведению, я проверил и использовал это в своей работе.

Joey

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

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;

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

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

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.

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

GroupBox имеет проверенное событие для этой цели, если вы используете 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();
     }

для разработчиков, использующих 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

Comments

    Ничего не найдено.