Ist es möglich RadioButtongruppen aus 2 Instanzen einer UserControl zu "verknüpfen"

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 28 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    Ist es möglich RadioButtongruppen aus 2 Instanzen einer UserControl zu "verknüpfen"

    Hi,

    kurze Frage:
    Ich habe mehrere Instanzen meiner erzeugten UserControl auf einer Form platzieren. Die UserControl besitzt auch jeweils einen Radiobutton. Ich hab nun festgestellt, dass die RadioButtons der einzelnen Instanzen nicht als "gruppiert" angesehen werden. Sprich kein anderer RadioButton wird unchecked wenn ich einen anderen RB anklicke! Ist es mit wenig Code oder dem Designer möglich die RadioButtons zu gruppieren oder sollte ich Checkboxen verwenden?
    codewars.com Rank: 4 kyu
    @nogood Diese Verknüpfung müsstest Du dann "zu Fuß" machen.
    Gib allen einen gemeinsamen CheckChanged-EventHandler.
    Beachte, dass es ein Checked- und ein Unchecked-Event gibt.
    Caste das Sender-Argument auf RadioButton und frage die Checked-Property ab.
    Das Unchecked-Event kannst Du ignorieren.
    Alle RadioButton außer dem Sender un-checkes Du und feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Na mal langsam. Ein UserControl hat ein RadioButton und bei 5 UserControls hast Du 5 RadioButtons und wenn einer davon angewählt wird, sollen die anderen 4 UCs ihre RadioButtons abwählen? Das klappt aber meines Erachtens nur, indem entweder das angewählte UC per RaiseEvent dem Form bescheid gibt und das Form allen anderen UCs anweist, dass sie ihre RadioButtons abwählen sollen oder ggf. mit ner UC-Shared-Property. Soweit ich RfGs Lösungsansatz verstehe, hat er mehrere unabhängige RadioButtons pro UC im Sinn, oder, @RodFromGermany?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed Nö.
    Klar, die Events müssen durchgereicht werden, aber wenn sie alle einen Handler haben, funktioniert das.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich hab mir für sowas ein RadioButtonBehavior gecodet.
    Da kann man RadioButtons registrieren, und das Behavior-Objekt kümmert sich dann um das gechecke.
    Es wirft auch ein Event, wenn die Anwahl wechselt, und gibt auch Auskunft, welcher RB aktuell gecheckt ist.
    Problem: Ich komme erst morgen an den Code ran.
    ;) ich hab einen Code mit CheckBoxen, d.h., man kann außerdem alles abwählen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @ErfinderDesRades
    @RodFromGermany
    @VaporiZed

    Danke für Euren Input. Falls Ihr ein paar Snippets teilen mögt gerne :P

    Wie so vieles ist auch das UserControl neu für mich (ich entdecke gerade wie toll das ist; gerade auch weil es mir einen Zugang zur Denkweise OOP gibt).

    Ich wollte das mit den RB mal selber versuchen und habe in der UserControl ein RaiseEvent erstellt:

    VB.NET-Quellcode

    1. 'im UserControl mp3player steht
    2. Public Event Cbxchecked(checked As Boolean)
    3. Private Sub CbTrkBVolMp3_CheckedChanged(sender As Object, e As EventArgs) Handles CbTrkBVolMp3.CheckedChanged
    4. RaiseEvent Cbxchecked(CbTrkBVolMp3.Checked)
    5. End Sub


    Wie macht man das mit UserControls (mp3player) die nicht codeseitig instanziert sind sondern über den Designer ins MainForm gezogen sind?
    Im MainForm mit

    VB.NET-Quellcode

    1. 'im MainForm steht
    2. Public WithEvents mp3player1 As Mp3Player

    geht es nicht. Da sagt der Kompiler das dies Object schon existiert! Wie bekomme ich das WithEvents an die Instanze "ran"?
    codewars.com Rank: 4 kyu

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „nogood“ ()

    Solche, die über den Designer aufs Form gezogen werden, stehen bereits in der FormX.Designer.VB-Datei drin, inkl. WithEvents. Einfach mal auf mp3player1 klicken und dann mit F12 oder über das Kontextmenü zur Definition wechseln. Daher kannst Du gleich mit

    VB.NET-Quellcode

    1. Private Sub mp3player1_Cbxchecked(checked As Boolean) Handles mp3player1.Cbxchecked
    2. End Sub
    weitermachen. Entweder selber schreiben oder im Code-Editor oben oder Deisgner im entsprechenden Fenster bei den Events raussuchen. Und dann dort in der Sub bzw. dem EventHandler an alle anderen UCs die Nachricht weitergeben: Schaltet Euren RadioButton ab.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed Ja Super hätte ich mal einfach ausprobieren sollen. Hab es eingetippt. Da ich dafür anscheinend zu blöd bin
    ​Einfach mal auf mp3player1 klicken und dann mit F12 oder über das Kontextmenü zur Definition wechseln.

    Wo kann ich denn auf das Objekt mp3player1 kicken und dann F12 (wenn ich im Designer das Objekt mp3player1 auf der MainForm ancklicke un dann F12 -> passiert nix)

    (ich kann es finden unter dem Menue Rechts und dann wenn ich den "Blitz"/Events drücke; meintes Du das?)
    codewars.com Rank: 4 kyu
    Nicht auf das UC im Designer selber klicken, sondern auf die Variable namens mp3player1, also im Code-Editor. Und dann mit F12 oder dem Kontextmenü zur Definition gehen.
    Ja, das mit dem Blitz ist das was ich u.a. meinte.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    VB.NET-Quellcode

    1. Private Sub mp3player1_Cbxchecked(checked As Boolean) Handles mp3player1.Cbxchecked
    2. End Sub
    wasisn das fürne Signatur :?:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Die vorgegebene des TEs aus Post#7, Codeblock#1, Zeile#2.
    Dass es schöner wäre, wenn er die Standardsignatur nimmt, indem er schreibt:

    VB.NET-Quellcode

    1. Public Event Cbxchecked As EventHandler
    2. '...
    3. RaiseEvent Cbxchecked(Me, Nothing)
    4. '...
    5. Private Sub mp3player1_Cbxchecked(sender As Object, e As EventArgs) Handles mp3player1.Cbxchecked
    6. End Sub

    weiß ich, aber so war die Vorgabe. Den Boolean-Parameter brauch er ja nicht, da das Event eh nur gefeuert werden soll, wenn ein UC meldet, dass sein RadioButton angewählt wurde. Und der Event-Name ist auch ausbaufähig.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Danke once again ...

    Bitte denkt dran, dass ich das alles so ziemlich zum ersten mal Code - > super das Ihr mich daraufhinweist. Im würde das sonst stumpf so weiter machen.

    Also Danke an :

    @RodFromGermany fürs anmerken
    @VaporiZed für das aufzeigen wie es eigentlich sein soll und nicht nur schreiben das das so nicht gut ist ;)

    Habt noch Geduld mit mir
    codewars.com Rank: 4 kyu
    Moin Leute ich bekomme es doch nicht hin ...
    Es sollen Checkboxen aus 2 instanzierten UserControls verbunden werden, dass immer nur eine gechecked ist (so wie Radiobutton // aber auch alles unchecked sein kann). Dann wenn das klappt, möchte ich die Verknüpfung der Checkboxen noch auf mehrere Checkboxen in einer anderen "fromEq" erweitern.
    Zu jeder Checkbox gehört eine Trackbar, wenn der User die Checkbox unter der Trackbar aktiviert soll diese Trackbar für Tasteneingabe aktiviert sein (daher dann noch die Zeile Main.trackBarChkBoxFocus = TrkBVolMp3).

    Im Moment sendet das Event als Sender die Klasse des UC und nicht die Checkbox (zur Laufzeit kommt der Fehler, dass das Objekt Mp3Player nicht in Checkbox gecastet werden kann). Wie mach man das?

    Mein Code bis hier hin ist :
    in Main:

    VB.NET-Quellcode

    1. Private lstCheckBoxes As List(Of CheckBox)
    2. ...
    3. Private Sub Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4. ...
    5. lstCheckBoxes = New List(Of CheckBox)
    6. lstCheckBoxes.Add(Mp3Player1.CbTrkBVolMp3)
    7. lstCheckBoxes.Add(Mp3Player2.CbTrkBVolMp3)
    8. End Sub
    9. Public Sub CbxTasterActiv(sender As Object, e As EventArgs) Handles Mp3Player1.CbxTasterActiv, Mp3Player2.CbxTasterActiv
    10. If CType(sender, CheckBox).Checked Then
    11. For Each chkbox As CheckBox In lstCheckBoxes
    12. If chkbox.Checked AndAlso CType(sender, CheckBox).Name <> chkbox.Name Then
    13. chkbox.Checked = False
    14. End If
    15. Next
    16. End If
    17. End Sub


    und in der UC:

    VB.NET-Quellcode

    1. Public Event CbxTasterActiv As EventHandler
    2. Private Sub CbTrkBVolMp3_CheckedChanged(sender As Object, e As EventArgs) Handles CbTrkBVolMp3.CheckedChanged
    3. Main.trackBarChkBoxFocus = TrkBVolMp3
    4. RaiseEvent CbxTasterActiv(Me, Nothing)
    5. End Sub


    Frage 1:
    Muss ich das Me ändern oder in Main die Checkbox der Klasse Mp3Player ansteuern. Bei beidem weiß ich nicht wie das geht.

    Danke für die Zeit zum antworten
    codewars.com Rank: 4 kyu
    Um die Frage zu beantworten: Du könntest statt dem Me bei RaiseEvent die UC-CheckBox hernehmen. Aber: belass es beim Me, caste den sender in ein ... richtig UserControl (oder wie die Klasse auch immer bei Dir heißt) und nimm dann dessen CheckBox her. Denn auf die kannst Du ja zugreifen, wenn Du weißt, dass es eines Deiner UserControls ist. Aber die For-Schleife lässt sich dank LINQ schönder gestalten. Ein Vorschlag:

    VB.NET-Quellcode

    1. Public Sub CbxTasterActiv(sender As Object, e As EventArgs) Handles Mp3Player1.CbxTasterActiv, Mp3Player2.CbxTasterActiv
    2. lstCheckBoxes.Where(Function(x) x IsNot DirectCast(sender, DeinUserControlKlassenname).CbTrkBVolMp3).ForEach(Sub(x) x.Checked = False)
    3. End Sub

    Aber:

    VB.NET-Quellcode

    1. Private Sub CbTrkBVolMp3_CheckedChanged(sender As Object, e As EventArgs) Handles CbTrkBVolMp3.CheckedChanged
    2. Main.trackBarChkBoxFocus = TrkBVolMp3
    3. RaiseEvent CbxTasterActiv(Me, Nothing)
    4. End Sub

    Was ist Main und was sucht es in dem Codeabschnitt? Dieser Code setzt voraus, dass dieses Main-Objekt existiert und ein Objekt oder eine Variable namens trackBarChkBoxFocus hat. Das sollte ein UserControl niemals über seinen Besitzer wissen. Was noch dazukommt: Main ist an sich ein Objekt, was Du nicht aktiv erstellt hast und ist daher tabu, wenn Du sauber programmieren willst. Daher die Frage, was Du mit dem Codestück machen lassen willst. Dann können wir Dir sagen, wie man es besser macht.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed

    Notiz:
    UserControl Klasse heißt -> UcMp3Player (hab es von Mp3Player in UcMp3Player umbenannt)

    Die UserControl besitzt eine Checkbox mit dem Namen -> CbTrkBVolMp3

    Die 2 Instanzen der UserControl auf der Main (Form) haben den Namen -> UcMp3Player1 und UcMp3Player2



    1. das Casten in den "richtigen" Typ hab ich jetzt dank deines Hinweises hinbekommen. Keine Kompilierfehler mehr (Gott sei dank 2 Tage rumgefrickel haben ein Ende).

    VB.NET-Quellcode

    1. Public Sub CbxTasterActiv(sender As Object, e As EventArgs) Handles UcMp3Player1.CbxTasterActiv, UcMp3Player2.CbxTasterActiv
    2. If CType(sender, UcMp3Player).CbTrkBVolMp3.Checked Then
    3. For Each chkbox As CheckBox In lstCheckBoxes
    4. If chkbox.Checked AndAlso CType(sender, UcMp3Player).CbTrkBVolMp3.Name <> chkbox.Name Then
    5. chkbox.Checked = False
    6. End If
    7. Next
    8. End If
    9. End Sub


    2. Richtig laufen tut der Code leider immer noch nicht. Die Checkboxen toggeln nicht (sie werden nicht auf unchecked gesetzt). Meine Vermutung ist, dass

    VB.NET-Quellcode

    1. CType(sender, UcMp3Player).CbTrkBVolMp3.Name <> chkbox.Name


    nicht das macht was ich will. Der Ausdruck vergleicht "nur" CbTrkBoxMp3 <> CbTrkBoxMp3 => also immer false der Zweig wird nie erreicht.

    Es müsste der "ganze String" UcMp3Player1.CbTrkBoxMp3 <> UcMp3Player2.CbTrkBoxMp3 verglichen werden. Da es sich ja nur im InstanzierungsNamen unterscheidet.
    Ich weiss leider nicht wie ich den Ausdruck schreiben muss, damit das passiert?

    3. Dein Vorschlag "...die For-Schleife lässt sich dank LINQ schöner gestalten" sieht absolut elegant aus! Leider bin ich weit davon entfernt das zu verstehen. Da müsste ich mich schon wieder mit so vielen neuen Sachen beschäftigen, dass ich mich wahrscheinlich noch mehr verstricken würde. Fürs erste hoffe ich, dass man auch so wie unter 2. beschrieben ans Ziel kommen kann. Das mit der Eleganz mach ich dann nächstes Jahr ;).

    4. Zu der unsäglichen Sache mit "Main.trackBarChkBoxFocus = TrkBVolMp3" in der UserControl, die dann auf eine Variable in der Main-Form verweist. Mein Instinkt hat mir auch gemeldet, dass da so nicht gut ist. Aber leider bin ich noch zu schlecht, als das ich das besser lösen kann (bis jetzt).
    Nach dem das Problem mit den Checkboxen gelöst wäre, müsste ja auch eine Konsequenz aus der Checked Checkbox erfolgen. Die Konsequenz soll sein, dass das Programm weis welche Trackbar (jede Trackbar "besitzt" eine Checkbox) gemeint ist und der User kann z.B. durch drücken der Taste + den Wert der Trackbar erhöhen, wo die Checkbox checkt ist.


    Also konkret hab ich noch zwei Baustellen 2. und 4.. Das Ausdruck muss richtig formuliert werden das UcMp3Player1.CbTrkBoxMp3 <> UcMp3Player2.CbTrkBoxMp3 verglichen wird und das die Information welche CheckBox checked ist dazuführt, dass z.B. die Variable trackBarFocus = UcMp3PlayerVol.TrkBar1 gesetzt werden kann.

    ----
    P. S. : was ich noch sehe und auch schlecht ist, ist dass ich leider 3 verschiedene Versionen von Checkbox Prefix munter mische cb, chk, cbx sollen immer auf Checkbox hinweisen. Sorry ich will mich bemühen in Zukunft immer cbx zu nehmen
    codewars.com Rank: 4 kyu

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „nogood“ ()

    Beachte unseren Codeunterschied. Du vergleichst Namen der UC-CheckBoxen. Die werden alle gleich sein. Ich vergleiche die CheckBoxen selbst, indem ich vom sender (das UC) die CheckBox hernehme und mit den CheckBoxen aus Deiner Liste vergleiche: If UC.CheckBox Is CheckBoxAusListe. Also: Kein Namensvergleich, sondern Identitätsvergleich.
    Daher belass es bei Deiner jetzigen For-Schleife mit:

    VB.NET-Quellcode

    1. If chkbox.Checked AndAlso CType(sender, UcMp3Player).CbTrkBVolMp3 IsNot chkbox Then


    Bzgl. TrackBar: Das liefe dann in der gleichen Sub ab wie der andere Code. Denn da hast Du den sender (= UC) und dessen TrackBar kannst Du ja speichern. Ist zwar auch alles ein bisken Pfeil-Rücken-Brust-Auge, aber für den Zweck reicht's.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @nogood Fang doch erst mal klein an und untersuch das Verhalten:
    Mach Dir 5 CheckBoxen auf eine Form und sonst nix.
    Alle bekommen den selben Check-Handler.
    Caste das Sender-Argument zu CheckBox, pack das in eine Variable.
    Teste, ob der Sender Unchecked ist => RAUS
    dann die Schleife mit dem Code von @VaporiZed.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @VaporiZed 1000 Thx. So geht es endlich ... (ObjectVergleich mit Is Isnot anstatt <> und .name)
    @RodFromGermany Ich hab schon angefangen, mir ein Project aufzubauen in dem ich meine Basis Snippets sammle. Dieses Problem kommt da rein.

    (wenigsten wusste ich schon wo der Fehler steckt, auch wenn ich ihn nicht beseitigen konnte ;) )


    Zu 4.
    Das mit dem Main.TrackBarFocus versuche ich jetzt so zu lösen, dass die UserControl Klasse Mp3Player ein Property bekommt, das dann von der MainForm ausgelesen werden kann. Im Event Fall, Checkbox checked, kann das Property "XYZ as Trackbar" von dem Object (UcMp3Player) in der Mainform ausgelesen werden. So rum sollte es dann richtig sein?

    Spannend wir es noch da ich auch aus einer anderen Klasse als aus der UcMp3Player Checkboxen und Trackbars ansteuern/setzen will. Ich denke, dass ich dann ein neues Event benutzen muss. Ich möchte eine 2te Form öffnen in dem z.B. 6 Checkboxen und 6 Trackbars sind und wieder die Trackbar für Tasteneingaben freischalten wenn die zugehörige Checkbox checked ist. Die neue Form bekommt ein UcEq und damit geht ja dann

    VB.NET-Quellcode

    1. If CType(sender, UcMp3Player).CbTrkBVolMp3.Checked Then
    nicht mehr und ich müsste

    VB.NET-Quellcode

    1. If CType(sender, UcEq).CbTrkBFreq1000.Checked Then

    benutzen.

    Ihr werdet es ja sehen, ob es klappt. Danke für die tolle Unterstützung
    codewars.com Rank: 4 kyu

    nogood schrieb:

    Im Event Fall, Checkbox checked, kann das Property "XYZ as Trackbar" von dem Object (UcMp3Player) in der Mainform ausgelesen werden. So rum sollte es dann richtig sein?
    Versteh ich insofern nicht, weil das UC doch schon eine zugängliche Komponente hat, die As TrackBar deklariert ist: das TrackBar-CE! Da braucht es doch keine Zusatzproperty mehr dazu. Main hat doch schon Zugriff. Genauso wie auf die CheckBox des UCs.

    Bzgl. neuem UC: Kommt drauf an. Wenn es effektiv nur eine umgewandelte/ausgebaute UcMp3Player-Klasse ist, könntest Du von der UcMp3Player-Klasse erben. Wenn es aber einen komplett anderen Aufbau und Funktionalität hat, dann richtig, braucht es ein eigenes Event. Oder Du machst ggf. ne MustInherit-Basisklasse, von der UcMp3Player und UcEq erben. Und das Event deklarierst Du in der Basisklasse. Dann können auch die "Erben" gemeinsam angesprochen werden, weil sie alle (abgeleitete) Basisklassenobjekte sind.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.