¿Qué botón de radio del grupo está marcado?

118

Usando WinForms; ¿Existe una mejor manera de encontrar el RadioButton marcado para un grupo? Me parece que el código siguiente no debería ser necesario. Cuando marca un RadioButton diferente, entonces sabe cuál desmarcar ... así que debería saber cuál está marcado. ¿Cómo extraigo esa información sin hacer muchas declaraciones if (o un cambio)?

     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;
     }
Porra
fuente
1
El código subyacente no sabe cuál desmarcar, simplemente itera todos los controles RadioButton debajo del mismo padre del control cambiado y desmarca el que se marcó previamente.
João Angelo
1
¿Está utilizando WinForms o ASP.Net?
SLaks

Respuestas:

219

Podrías usar LINQ:

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

Tenga en cuenta que esto requiere que todos los botones de opción estén directamente en el mismo contenedor (por ejemplo, Panel o Formulario) y que solo haya un grupo en el contenedor. Si ese no es el caso, puede hacer List<RadioButton>s en su constructor para cada grupo, luego escribir list.FirstOrDefault(r => r.Checked).

SLaks
fuente
Si ese fuera s.FirstOrDefaulten lugar de list.FirstOrDefaulten el segundo párrafo de su respuesta?
@Phoenix: ses una pluralización, no un nombre de variable.
SLaks
Excelente respuesta, pero realmente no respondió a la pregunta principal de OP. Mira mi respuesta.
D'Hag
para ustedes, chicos de vb.net, les ahorraré un viaje al convertidor Telerik: Dim checkButton = radConnections.Controls.OfType (Of RadioButton) (). FirstOrDefault (Function (r) r.Checked)
JoshYates1980
36

Puede conectar los CheckedEvents de todos los botones contra un controlador. Allí puede obtener fácilmente la casilla de verificación correcta.

// 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;
    }
}
Poli
fuente
Debería ser esto en su lugar - if (((RadioButton) sender) .Checked)
Frank Tzanabetis
1
No hay CheckedChanged en el RadioButton de WPF, ¿de dónde lo sacaste?
Murhaf Sousli
26

Para aquellos sin 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;
}
João Angelo
fuente
12

El OP quería obtener el RadioButton marcado POR GRUPO. Si bien la respuesta de @SLaks es excelente, realmente no responde a la pregunta principal del OP. Para mejorar la respuesta de @SLaks, simplemente lleve el LINQ un paso más allá.

Aquí hay un ejemplo de mi propio código de trabajo. Según WPF normal, mis RadioButtons están contenidos en un Grid(llamado "myGrid") con un montón de otros tipos de controles. Tengo dos grupos RadioButton diferentes en la cuadrícula.

Para obtener el RadioButton marcado de un grupo en particular:

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

Si su código tiene la posibilidad de que no se verifique ningún RadioButtons, entonces use SingleOrDefault()(Si no estoy usando botones de tres estados, siempre configuro un botón "IsChecked" como selección predeterminada).

D'Hag
fuente
1
r.GroupName == "GroupName" y r.IsChecked son de diferentes tipos (bool y bool?), debería haber usado r.IsChecked.Value, que es de tipo bool.
Mike
1
intente .Where(r => r.GroupName == "GroupName" && r.IsChecked == true)porque r.IsCheckedes una propiedad bool anulable.
Firnas
¿A qué se refiere myGrid aquí?
Unnikrishnan
@Mike ¿Podrías decir qué es "radioButtons" aquí?
Bella Swan
1
@BellaSwan: echa un vistazo al código: creas una lista de todos los botones de opción y la asignas a una variable. Y luego, en la misma variable, debe ejecutar la selección Where y asignarla a rbTarget.
Mike
5

Puede utilizar el evento CheckedChanged para todos sus RadioButtons. Senderserán los RadioButtons no marcados y marcados.

tanascius
fuente
1

Puede utilizar un método de extensión para iterar la colección Parent.Controls de RadioButton. Esto le permite consultar otros RadioButtons en el mismo ámbito. Usando dos métodos de extensión, puede usar el primero para determinar si algún RadioButton del grupo está seleccionado y luego usar el segundo para obtener la selección. El campo Etiqueta de RadioButton se puede utilizar para mantener un Enum para identificar cada RadioButton en el 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;
    }

Aquí hay un patrón de uso típico:

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

Además del cableado CheckedChangedEvent, se podría usar la propiedad "Etiqueta" de los controles para distinguir entre los botones de opción ... una alternativa (código espagueti) sería la propiedad "TabIndex"; P

Binkan Salaryman
fuente
significa que puede usar rápidamente el cambio de mayúsculas y minúsculas en la identificación del botón de radio seleccionado (usando la propiedad System.Windows.Forms.Control.Tag) por favor no califique si simplemente no entiende mi adición a la pregunta.
Binkan Salaryman
1

A veces, en situaciones como esta, extraño mi juventud, cuando Access era mi veneno preferido, y podía darle a cada botón de radio de un grupo su propio valor.

Mi truco en C # es usar la etiqueta para establecer el valor, y cuando hago una selección del grupo, leo el valor de la etiqueta del botón de radio seleccionado. En este ejemplo, directionGroup es el grupo en el que tengo cuatro cinco botones de radio con "Ninguno" y "NE", "SE", "NW" y "SW" como etiquetas en los otros cuatro botones de radio.

Usé proactivamente un botón para capturar el valor del botón marcado, porque al asignar un controlador de eventos a todos los eventos CHeckCHanged de los botones, CADA botón se dispara, porque cambiar uno los cambia todos. Entonces, el valor de remitente es siempre el primer RadioButton del grupo. En su lugar, utilizo este método cuando necesito averiguar cuál está seleccionado, con los valores que quiero recuperar en la propiedad Etiqueta 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());
    }

FYI, he probado y utilizado esto en mi trabajo.

Joey

Joseph Morgan
fuente
Modificando solo el resultado de 'FormatableString', pude usar el código en mi programa. Tampoco estaba al tanto de radioButton Tag. Así es como deben ser las respuestas. Gran señor.
Unnikrishnan
0

si quieres guardar la selección en un archivo o cualquier otra cosa y llamarla más tarde, aquí lo que hago

string[] lines = new string[1];

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

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

entonces llámalo con

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

Si desea obtener el índice del botón de opción seleccionado dentro de un control, puede 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;
}

Ejemplo de uso:

int index = getCheckedRadioButton(panel1);

El código no está tan bien probado, pero parece que el orden del índice es de izquierda a derecha y de arriba a abajo, como cuando se lee un texto. Si no se encuentra ningún botón de opción, el método devuelve -1.

Actualización: resultó que mi primer intento no funcionó si no hay un botón de opción dentro del control. Agregué un bloque de prueba y captura para solucionarlo, y el método ahora parece funcionar.

matsolof
fuente
0

El GroupBox tiene un evento Validado para este propósito, si está usando 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
fuente
0

Para desarrolladores que usan 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

fuente