Qual botão de rádio do grupo está marcado?

118

Usando WinForms; Existe uma maneira melhor de encontrar o RadioButton marcado para um grupo? Parece-me que o código abaixo não deve ser necessário. Quando você marca um RadioButton diferente, ele sabe qual desmarcar ... então deve saber qual está marcado. Como faço para obter essas informações sem fazer muitas instruções if (ou uma mudança).

     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;
     }
Billy
fonte
1
O código subjacente não sabe qual desmarcar, ele apenas itera todos os controles RadioButton abaixo do mesmo pai do controle alterado e desmarca aquele previamente verificado.
João Angelo
1
Você está usando WinForms ou ASP.Net?
SLaks

Respostas:

219

Você pode usar LINQ:

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

Observe que isso requer que todos os botões de opção estejam diretamente no mesmo contêiner (por exemplo, Painel ou Formulário) e que haja apenas um grupo no contêiner. Se esse não for o caso, você pode criar List<RadioButton>s em seu construtor para cada grupo e, em seguida, escrever list.FirstOrDefault(r => r.Checked).

SLaks
fonte
Que deveria ser s.FirstOrDefault, em vez de list.FirstOrDefaultno segundo parágrafo da sua resposta?
@Phoenix: sé uma pluralização, não um nome de variável.
SLaks
Excelente resposta, mas não respondeu realmente à pergunta principal de OP. Veja minha resposta.
D'Hag
para vocês, pessoal do vb.net, vou economizar uma viagem para o conversor Telerik: Dim checkedButton = radConnections.Controls.OfType (Of RadioButton) (). FirstOrDefault (Function (r) r.Checked)
JoshYates1980
36

Você pode conectar os CheckedEvents de todos os botões a um manipulador. Lá você pode obter facilmente a caixa de seleção correta.

// 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;
    }
}
Bobby
fonte
Em vez disso, deveria ser - if (((RadioButton) sender). Verificado)
Frank Tzanabetis
1
Não há CheckedChanged no RadioButton do WPF de onde você o tirou?
Murhaf Sousli
26

Para quem não tem 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;
}
Joao angelo
fonte
12

O OP queria obter o RadioButton BY GROUP verificado. Embora a resposta de @SLaks seja excelente, ela realmente não responde à pergunta principal do OP. Para melhorar a resposta de @SLaks, basta levar o LINQ um passo adiante.

Aqui está um exemplo do meu próprio código de trabalho. Por WPF normal, meus RadioButtons estão contidos em um Grid(denominado "myGrid") com vários outros tipos de controles. Tenho dois grupos RadioButton diferentes no Grid.

Para obter o RadioButton verificado de um grupo específico:

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

Se o seu código não tiver a possibilidade de nenhum RadioButtons ser verificado, use SingleOrDefault()(Se eu não estiver usando botões tri-state, então sempre defino um botão "IsChecked" como uma seleção padrão).

D'Hag
fonte
1
r.GroupName == "GroupName" e r.IsChecked são de tipos diferentes (bool e bool?), você deve ter usado r.IsChecked.Value, que é do tipo bool.
Mike
1
tente .Where(r => r.GroupName == "GroupName" && r.IsChecked == true)porque r.IsCheckedé uma propriedade bool anulável.
Firnas
a que myGrid se refere aqui.
Unnikrishnan
@Mike Você poderia dizer o que é "radioButtons" aqui?
Bella Swan
1
@BellaSwan - dê uma olhada no código - você cria uma lista de todos os botões de opção e atribui a uma variável. E então, na mesma variável, você precisa executar a seleção Where e atribuí-la a rbTarget.
Mike
5

Você pode usar o evento CheckedChanged para todos os seus RadioButtons. Senderserá o RadioButtons desmarcado e verificado.

tanascius
fonte
1

Você pode usar um método Extension para iterar a coleção Parent.Controls do RadioButton. Isso permite que você consulte outros RadioButtons no mesmo escopo. Usando dois métodos de extensão, você pode usar o primeiro para determinar se algum RadioButtons no grupo está selecionado e, em seguida, usar o segundo para obter a seleção. O campo RadioButton Tag pode ser usado para conter um Enum para identificar cada RadioButton no grupo:

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

Aqui está um padrão de uso típico:

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

Além da fiação CheckedChangedEvent, pode-se usar a propriedade "Tag" dos controles para distinguir entre os botões de opção ... uma alternativa (código espaguete) seria a propriedade "TabIndex"; P

Binkan Salaryman
fonte
isso significa que você pode usar rapidamente o caso de switch no id do botão de rádio selecionado (usando a propriedade System.Windows.Forms.Control.Tag) por favor, não avalie se você simplesmente não entender minha adição à questão.
Binkan Salaryman
1

Às vezes, em situações como essa, sinto falta da minha juventude, quando o Access era meu veneno de escolha, e eu poderia dar a cada botão de opção em um grupo seu próprio valor.

Meu hack em C # é usar a tag para definir o valor, e quando eu faço uma seleção no grupo, eu leio o valor da tag do radiobutton selecionado. Neste exemplo, directionGroup é o grupo no qual tenho quatro cinco botões de opção com "Nenhum" e "NE", "SE", "NW" e "SW" como as tags nos outros quatro botões de opção.

Usei proativamente um botão para capturar o valor do botão marcado, porque atribuir um manipulador de eventos a todos os eventos CHeckCHanged dos botões faz com que CADA botão seja disparado, porque alterar um deles altera todos. Portanto, o valor de sender é sempre o primeiro RadioButton do grupo. Em vez disso, uso esse método quando preciso descobrir qual está selecionado, com os valores que desejo recuperar na propriedade Tag de cada 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());
    }

Para sua informação, testei e usei isso em meu trabalho.

Joey

Joseph Morgan
fonte
Modificando apenas o resultado 'FormatableString', consegui usar o código em meu programa. Eu também não conhecia o radioButton Tag. É assim que as respostas devem ser. Grande senhor.
Unnikrishnan
0

se você quiser salvar a seleção em arquivo ou qualquer outro e chamá-lo depois, aqui o que faço

string[] lines = new string[1];

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

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

então ligue com

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

Se você deseja obter o índice do botão de opção selecionado dentro de um controle, pode usar este método:

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

Exemplo de uso:

int index = getCheckedRadioButton(panel1);

O código não foi bem testado, mas parece que a ordem do índice é da esquerda para a direita e de cima para baixo, como ao ler um texto. Se nenhum botão de opção for encontrado, o método retornará -1.

Atualização: Minha primeira tentativa não funcionou se não houver um botão de opção dentro do controle. Eu adicionei um bloco try and catch para corrigir isso, e o método agora parece funcionar.

Matsolof
fonte
0

O GroupBox possui um evento Validado para este fim, caso você esteja utilizando 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();
     }
Bede Amarasekara
fonte
0

Para desenvolvedores que usam 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

fonte