Który przycisk radiowy w grupie jest zaznaczony?


118

Korzystanie z WinForms; Czy jest lepszy sposób na znalezienie zaznaczonego RadioButton dla grupy? Wydaje mi się, że poniższy kod nie powinien być potrzebny. Kiedy sprawdzasz inny RadioButton, wtedy wie, który z nich odznaczyć… więc powinien wiedzieć, który jest zaznaczony. Jak pobrać te informacje bez wykonywania wielu instrukcji if (lub przełączania).

     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
Kod bazowy nie wie, który z nich należy odznaczyć, po prostu iteruje wszystkie kontrolki RadioButton poniżej tego samego elementu nadrzędnego zmienionej kontrolki i usuwa zaznaczenie poprzednio zaznaczonej.
João Angelo

1
Czy używasz WinForms lub ASP.Net?
SLaks

Odpowiedzi:


219

Możesz użyć LINQ:

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

Zauważ, że wymaga to, aby wszystkie przyciski radiowe znajdowały się bezpośrednio w tym samym kontenerze (np. Panel lub Formularz), a kontener zawiera tylko jedną grupę. Jeśli tak nie jest, możesz utworzyć List<RadioButton>s w konstruktorze dla każdej grupy, a następnie napisz list.FirstOrDefault(r => r.Checked).


Czy powinno to być s.FirstOrDefaultzamiast list.FirstOrDefaultw drugim akapicie Twojej odpowiedzi?

@Phoenix: sto liczba mnoga , a nie nazwa zmiennej.
SLaks

Doskonała odpowiedź, ale tak naprawdę nie odpowiedział na główne pytanie OP. Zobacz moją odpowiedź.
D'Hag

dla was vb.net, zaoszczędzę wam wycieczkę do konwertera Telerik: Dim CheckedButton = radConnections.Controls.OfType (Of RadioButton) (). FirstOrDefault (Function (r) r.Checked)
JoshYates1980

36

Możesz połączyć CheckedEvents wszystkich przycisków z jednym programem obsługi. Tam możesz łatwo uzyskać prawidłowe pole wyboru.

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

Powinien być zamiast tego - if (((RadioButton) sender) .Checked)
Frank Tzanabetis Kwietnia

1
Nie ma CheckedChanged w RadioButton WPF, skąd go masz?
Murhaf Sousli

26

Dla osób bez 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 chciał uzyskać sprawdzone RadioButton WEDŁUG GRUPY. Chociaż odpowiedź @SLaks jest doskonała, tak naprawdę nie odpowiada na główne pytanie OP. Aby poprawić odpowiedź @SLaks, po prostu idź o krok dalej LINQ.

Oto przykład z mojego własnego działającego kodu. W normalnym WPF moje RadioButtons są zawarte w Grid(o nazwie „myGrid”) z kilkoma innymi typami kontrolek. Mam dwie różne grupy RadioButton w siatce.

Aby pobrać zaznaczony element RadioButton z określonej grupy:

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

Jeśli w Twoim kodzie nie ma możliwości sprawdzania RadioButtons, użyj SingleOrDefault()(Jeśli nie używam przycisków trójstanowych, zawsze ustawiam jeden przycisk „IsChecked” jako domyślny).


1
r.GroupName == "GroupName" i r.IsChecked są różnych typów (bool i bool?), powinieneś był użyć r.IsChecked.Value, który jest typu bool.
Mike

1
try, .Where(r => r.GroupName == "GroupName" && r.IsChecked == true)ponieważ r.IsCheckedwłaściwość bool dopuszcza wartość null.
Firnas

do czego odnosi się myGrid.
Unnikrishnan

@Mike Czy możesz powiedzieć, co to jest „radioButtons” tutaj?
Bella Swan

1
@BellaSwan - spójrz na kod - tworzysz listę wszystkich przycisków radiowych i przypisujesz ją do zmiennej. Następnie na tej samej zmiennej musisz uruchomić wybór Where i przypisać go do rbTarget.
Mike


1

Możesz użyć metody Extension, aby wykonać iterację kolekcji Parent.Controls RadioButton. Pozwala to na wysyłanie zapytań do innych RadioButtons w tym samym zakresie. Korzystając z dwóch metod rozszerzania, możesz użyć pierwszej, aby określić, czy wybrane są jakiekolwiek RadioButtons w grupie, a następnie użyć drugiej, aby uzyskać zaznaczenie. Pole Tag RadioButton może służyć do przechowywania Enum w celu zidentyfikowania każdego RadioButton w grupie:

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

Oto typowy wzorzec użycia:

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

1

Oprócz okablowania CheckedChangedEvent można by użyć właściwości Controls "Tag" do rozróżnienia przycisków radiowych ... alternatywą (kodu spaghetti) byłaby właściwość "TabIndex"; P


oznacza to, że możesz szybko użyć przełączników na wybranym identyfikatorze radiobutton (używając właściwości System.Windows.Forms.Control.Tag), nie oceniaj niżej, jeśli po prostu nie rozumiesz mojego dodatku do pytania.
Binkan Salaryman,

1

Czasami w takich sytuacjach tęsknię za młodością, kiedy Access był moją wybraną trucizną i mogłem nadać każdemu przyciskowi w grupie własną wartość.

Moja sztuczka w C # polega na używaniu tagu do ustawiania wartości, a kiedy dokonuję wyboru z grupy, czytam wartość tagu wybranego radiobutton. W tym przykładzie directionGroup to grupa, w której mam cztery pięć przycisków radiowych z tagami „None” i „NE”, „SE”, „NW” i „SW” na pozostałych czterech radiobuttons.

Aktywnie użyłem przycisku do przechwycenia wartości zaznaczonego przycisku, ponieważ przypisanie jednego programu obsługi zdarzenia do zdarzenia CHeckCHanged wszystkich przycisków powoduje uruchomienie KAŻDEGO przycisku, ponieważ zmiana jednego zmienia je wszystkie. Zatem wartością nadawcy jest zawsze pierwszy element RadioButton w grupie. Zamiast tego używam tej metody, gdy muszę dowiedzieć się, która z nich jest wybrana, z wartościami, które chcę pobrać we właściwości Tag każdego 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, przetestowałem i wykorzystałem to w mojej pracy.

Joey


Modyfikując tylko wynik „FormatableString”, mogłem użyć kodu w moim programie. Nie wiedziałem również o tagu radioButton. Tak powinny wyglądać odpowiedzi. Wielki Panie.
Unnikrishnan

0

jeśli chcesz zapisać zaznaczenie do pliku lub innego i zadzwonić później, oto co robię

string[] lines = new string[1];

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

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

następnie zadzwoń do tego za pomocą

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

0

Jeśli chcesz uzyskać indeks wybranego przycisku radiowego wewnątrz kontrolki, możesz użyć tej metody:

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

Przykładowe zastosowanie:

int index = getCheckedRadioButton(panel1);

Kod nie jest dobrze przetestowany, ale wydaje się, że kolejność indeksów jest od lewej do prawej i od góry do dołu, jak podczas czytania tekstu. Jeśli nie zostanie znaleziony żaden przycisk radiowy, metoda zwraca -1.

Aktualizacja: Okazało się, że moja pierwsza próba nie zadziałała, jeśli w kontrolce nie ma przycisku radiowego. Dodałem blok try i catch, aby to naprawić, i metoda wydaje się teraz działać.


0

GroupBox ma w tym celu zdarzenie Validated, jeśli używasz 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

Dla programistów używających 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.