Steuerelement in Groupbox aus Modul ansprechen

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

Es gibt 59 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Steuerelement in Groupbox aus Modul ansprechen

    Hallo,
    ich habe u.a. in einer Groupbox "gruppe1" mehrere Steuerelemente Label mit dem Namen "lbl_maschine1" "lbl_maschine2" usw.
    In meinem Programm rufe ich eine Sub in einem Modul auf, an die ich die Maschinennnummer als Variable "maschine" übergebe. Die Routine soll dann bspw. das Label der Maschine 1 mit einem Text versehen. Mit folgendem Code, in dem ich das Label in der Groupbox direkt anspreche geht es:
    frm_main.gruppe1.Controls.(".lbl_maschine" & maschine).Text = Speed

    Nun würde ich aber gern die übergene Variable "maschine" dazu nutzen, dass ich auch die "gruppe1" im vorderen Teil der Anweisung ansprechen kann. Schreibe ich aber:
    frm_main.gruppe(maschine).Controls.(".lbl_speed" & maschine).Text = Speed
    oder ähnliches, verweigert er mir die Arbeit.

    Hat jemand vielleicht ein Idee oder geht das überhaupt?

    Danke und Gruß,

    Alex.
    ==> seid .net zueinander :D <3 <==
    Hamburger, danke für den Tipp. Aufgrund Laienstatus kommt ich ohne Beispiel aber nicht voran. Kannst du mir da unter die Arme greifen.
    Die Sub im Modul heißt:

    Quellcode

    1. Sub druckmaschinen(ByVal maschine As String)


    Und die rufe ich aus der Form mit

    Quellcode

    1. Call druckmaschinen(54)
    auf, was eigentlich auch super klappt.

    ==> Frage gestellt und 5min später 2 Antworten: 10 von 10 Puntken :) !!!
    ==> seid .net zueinander :D <3 <==
    Was soll das Call?

    Gib deinem Projekt bitte "OPTION STRICT ON" unter Projekteinstellungen. Du erwartest einen String und übergibst eine Zahl... Da ist ein vollkommendes Durcheinander.

    Vielleicht wäre es sinnvoll, wenn du dein Vorhaben mehr beschreibst. Was willst du überhaupt erreichen?
    Hallo,
    falls deine Labels den Namen der Maschine haben, kannst du es recht einfach machen.
    Im Beispiel wird angenommen, das die Labels so heissen:
    lbl_maschine1 - lbl_maschine2 - lbl_maschine3

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    2. SetMaschinenText(2, "Nummer 2")
    3. End Sub
    4. Private Sub SetMaschinenText(Maschinennummer As Integer, Text As String)
    5. For Each ctrl As Control In GroupBox1.Controls
    6. If TypeOf ctrl Is Label Then
    7. If ctrl.Name = "lbl_maschine" & Maschinennummer Then
    8. ctrl.Text = Text
    9. End If
    10. End If
    11. Next
    12. End Sub

    Was passiert hier?
    Es wird die Nummer der Maschine übergeben und z.B. ein Text
    Die Sub "SetMaschinentext" durchsucht alle Labels die sich in der Groubbox1 befinden.
    Wurde eines gefunden, wird verglichen ob der Name stimmt. Wenn ja.. wird der Text gesetzt.

    Vielleicht genügt das ja als Einstiegspunkt.
    In deinem Modul gibt es die Prozedur, in der du den Maschinen-Text setzt.
    z.B.

    VB.NET-Quellcode

    1. ​Public Sub setMaschinenText(ByVal maschine As Label, ByVal message As String)
    2. maschine.Text = message
    3. End Sub

    in deinem Formular rufst du dann einfach folgendes auf. (z.B. Beim Klick auf einen Button)

    VB.NET-Quellcode

    1. ​Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. setMaschinenText(Label1, "Mein Text")
    3. End Sub

    Mit dem ersten Parameter übergibst du das Label-Objekt, sodass deine Prozedur im Modul, das Label kennt und auf alle Eigenschaften zugreifen kann, ohne den Umweg über die Groupbox.
    @RoulettePilot:

    Das ist schon mal ein guter Ansatz. Nur müsste ich deinen Code dann für jede Groupbox nochmal schreiben, da du ja mit

    Quellcode

    1. GroupBox1.Controls
    die zu durchsuchende Groupbox direkt ansprichst. Und genau das wollte ich eigentlich vermeiden und die "1" darin irgendwie mit der übergebenen Variable verknüpfen.
    ==> seid .net zueinander :D <3 <==
    Auch wenn hier ein Modul vielleicht nicht der richtige Weg ist hier mal ein kleiner Ansatz:
    - Übergib der Methode nicht einen String sondern direkt das Label (wie oben bereits schon geschrieben wurde).
    - Das Label hat eine Eigenschaft "Parent" welche das übergeordnete Container-Steuerelement zurückgibt (in deinem Fall die Groupbox)

    Hier ein Beispiel:

    VB.NET-Quellcode

    1. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    2. DoSomething(Label1, "Label Text", "GroupboxText")
    3. End Sub
    4. Private Sub DoSomething(lbl As Label, lblText As String, prntText As String)
    5. lbl.Text = lblText
    6. lbl.Parent.Text = prntText
    7. End Sub


    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    im Prinzip auf die gleiche Weise, indem du die Form durchsuchst (also alle Groupboxen) die sich in der form befinden.
    also in der Art..

    for each.... in Form.controls..
    if typeof .. groupbox then
    .. if Name ... then
    und hier dann praktisch die Routine von Settext
    Exit Sub..
    end if
    ....
    @HamburgerJungeJr .. evtl. weil er nur die Nummer hat, nicht aber das Objeclt selbst.
    Und... falls mal eine Neue Machine kommt, oder man sich vertippt. gibt es keinen Fehle während das Teil Läuft.
    (kann bei Maschinen schon echt ein Problem darstellen, wenn das Steuerprogramm eingeschnappt ist und schlafen geht)

    @Axxxxxl .. so könnte es dann aussehen:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    2. SetMaschine(2, 1, "blubb")
    3. End Sub
    4. Private Sub SetMaschine(Gruppe As Integer, Maschine As Integer, Text As String)
    5. ' Gruppe wäre die Gruppe in der das label sein soll
    6. ' Maschine wäre die Maschinennummer
    7. ' da keine 2 Label mit dem gleichen Namen auftauchen können. muss eine gruppe z.b. lbl_maschine1 heissten, die andere lbl_speed1
    8. ' also können wir nicht mehr direkt auf den Namen vergleichen, soondern schauen nur hinten nach der nummer
    9. For Each ctrl As Control In Me.Controls
    10. If TypeOf ctrl Is GroupBox Then
    11. If ctrl.Name.EndsWith(Gruppe.ToString) Then
    12. ' das die richtige Groupbox wurde gefunden
    13. For Each lctrl As Control In ctrl.Controls
    14. If TypeOf lctrl Is Label Then
    15. If lctrl.Name.EndsWith(Maschine.ToString) Then
    16. ' das richtige Label gefunden
    17. lctrl.Text = Text
    18. Exit Sub ' Ferddich
    19. End If
    20. End If
    21. Next
    22. End If
    23. End If
    24. Next
    25. End Sub

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

    Willkommen im Forum. :thumbup:

    Axxxxxl schrieb:

    VB.NET-Quellcode

    1. frm_main.gruppe1.Controls.(".lbl_maschine" & maschine).Text = Speed
    ist etwas sehr grottig, sorry.
    1. Speed ist, denke ich, ein numerischer Wert, .Text ist ein String. Mach zunächst Option Strict On, da machst Du keine automatischen Konvertierungen mehr.
    2. Arbeite objektorientiert, pack Deine Maschinen-Sachen in eine Klasse, nicht aber in ein Modul. Da kannst Du Dir für jede Maschine / Baugruppe eine separate Instanz anlegen.
    3. Trenne Daten und GUI, lies Controls aus, konvertiere das in Daten, arbeite damit und weise den Controls die Ergebnisse zu. Dafür haben alle Object's die Methode ToString().
    4. Auch Dialoge / Fenster liegen als Instanz vor, nur nicht im VB6-Kompatibilitätsmodus. Gugst Du hier.
    Auch wenn das vielleicht etwas heftig ist, solltest Du Dich von Anfang an bemühen, einen ordentlichen Code-Stil zu entwickeln
    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!
    @fichz
    Was wäre statt dem Modul die bessere Variante?

    @all:
    Also mal kurz zur Erklärung des Gesamtsystems:
    Ich übergebe an die Sub die Maschinennummer. Mit dieser Sub wird dann eine bestimmte URL in unserem Netzwerk aufgerufen wo Maschinendaten hinterlegt sind. Vorher hatte ich die Aufrufe und das Setzen der Labeltexte für jede Maschine einzeln programmiert. Aber bei mehr als 3 Maschinen macht es keinen Spaß mehr, wenn du eine Sache ändern und dazu 1000 Code überprüfen musst. Deswegen die Idee mit der Sub und der Übergabe der Maschinennummer:

    1. Übergabe von bspw. Maschinennummer "54"
    2. AUfruf der Sub im Modul
    3. Abruf der Daten der entsprechenden Maschine per XML (funktioniert alles einwandfrei)
    4. Darstellen der Daten in den entsprechenden Labels in der Groupbox der Maschine
    Für den Speed der Maschine 54 schreibe ich dazu eben:

    Quellcode

    1. frm_main.grp_ma54.Controls(".lbl_speed" & ma_nummer).Text = Speed
    was auch geht, da ich durch das "grp_ma54" die Gruppe direkt anspreche.
    Ich würde aber eben gern sagen:

    Quellcode

    1. frm_main.(".grp_ma" & ma_nummer).Controls(".lbl_speed" & ma_nummer).Text = Speed
    Was aber in einer Fehlermeldung endet.

    @RoulettePilot:
    So gesehen stimmt es ja, dass mir sowohl der Name der Groupbox als auch der Name des Labels bekannt sind und ich eigentlich nicht alles danach durchsuchen müsste?!

    @RodFromGermany
    Liegt auch sicherlich daran, dass ich vor paar Jahren VB6 genutzt habe und die Feinheiten und Vorteile von .NET sicher nicht ansatzweise kenne. Ich versuche aber auch, den Code im Rahmen meiner Möglichkeiten zu optimieren.
    ==> seid .net zueinander :D <3 <==

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

    Sinnvoll wäre eine Klasse für Maschinendaten MyMaschine. Für jede Maschine erstellst du ein Objekt dieser Klasse und schreibst alles, was du aus XML rausliest, da rein (in die einzelnen Propertys). Du kannst in deiner Form eine List(Of MyMaschine) anlegen, wo du diese Objekte reintust.
    Dann erstellst du ein UserControl MyMaschGroupBox, wo diese Groupbox mit den einzelnen Controls drin sind.
    Du fügst diese UserControls der Form zu und erstellst zusätzlich eine List(Of MyMaschGroupBox). Der Index in der List von deinen Maschinenobjekten würde dem Index der List von deinen UserControls entsprechen.
    Dann brauchst du nur in der Schleife die List von Maschinen durchgehen und dem zugehörigen UserControl die Maschinendaten übergeben.
    Fertig.

    Ist eine saubere OOP-Lösung, ohne Suche nach Controlsnamen...

    EDIT: habe gerade gesehen, dass @RodFromGermany das mit den Klassen für Maschinen schon angesprochen hatte...

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

    @Sonne75:
    Danke für die Tipps. Allerdings "kollidiert" das mit meinem Wissensstand bezüglich VB.net.
    Ich habe eben die Groupboxen und Labels mit "Hand" gezeichnet da ich nicht weiß wie man "ein Objekt dieser Klasse" erstellt oder ein "Usercontrol der Form" zuführe :-/
    Wenn es nicht geht muss ich es eben für jede Maschine wieder einzeln schreiben.

    Hier mal der Code der ganzen Sub wobei zu beachten ist, dass außer beim dem Label "lbl_speedma54" alles noch aus der Zeit steht, als jede Maschine einzeln und explizit abgearbeitet wurde:

    VB.NET-Quellcode

    1. Sub druckmaschinen(ByVal ma_nummer As Integer, ma_text As String, grp_name As String)
    2. 'URLs für XML Daten der Maschinen festlegen
    3. 'Druckmaschinen
    4. If ma_nummer = "54" Then HTTPAdresse = "http://lblmeew131"
    5. If ma_nummer = "55" Then HTTPAdresse = "http://lblmeew132"
    6. If ma_nummer = "56" Then HTTPAdresse = "http://lblmeew120"
    7. 'Schneidmaschinen
    8. If ma_nummer = "29" Then HTTPAdresse = "http://lblmeew122"
    9. If ma_nummer = "30" Then HTTPAdresse = "http://lblmeew123"
    10. If ma_nummer = "31" Then HTTPAdresse = "http://lblmeew126"
    11. If ma_nummer = "32" Then HTTPAdresse = "http://lblmeew128"
    12. XMLString = Client.DownloadString(HTTPAdresse)
    13. xml_Doc.LoadXml(XMLString) ' ... XML-Datei aus String laden
    14. xml_Knoten = xml_Doc.SelectSingleNode("/bde/application/geschwindigkeit") ' Mit XPath ab Anfang zum gesuchten Konten gehen
    15. Double.TryParse(xml_Knoten.InnerText.Replace(".", ","), Wert)
    16. Speed = System.Math.Truncate(Wert).ToString ' Gefundenen Wert als Ganzzahl gerundet anzeigen
    17. frm_main(".grp_ma" & ma_nummer).Controls(".lbl_speed" & ma_nummer).Text = Speed
    18. 'frm_main.lbl_speed54.Text = Speed
    19. 'Progressbar anpassen
    20. frm_main.bar_54.Value = System.Math.Truncate(Wert).ToString
    21. 'Hintergrund entsprechend Geschwindigkeit färben und LEDs laden
    22. If frm_main.lbl_speed54.Text <= 1 Then
    23. frm_main.grp_ma54.BackColor = System.Drawing.Color.FromArgb(255, 192, 192)
    24. frm_main.pic_led_54.Image = CCL_Info_Monitor.My.Resources.Resources.Redlight
    25. Else
    26. frm_main.grp_ma54.BackColor = Color.LightGreen
    27. frm_main.pic_led_54.Image = CCL_Info_Monitor.My.Resources.Resources.Greenlight
    28. End If
    29. '----------------------------------------------------------------------------------------------------------------
    30. 'Produktivstatus anzeigen
    31. Dim produktiv As String
    32. xml_Doc.LoadXml(XMLString) ' ... XML-Datei aus String laden
    33. xml_Knoten = xml_Doc.SelectSingleNode("/bde/aktuell_produktiv") ' Mit XPath ab Anfang zum gesuchten Konten gehen
    34. produktiv = xml_Knoten.InnerText
    35. If produktiv = "1" Then
    36. frm_main.lbl_produktiv54.Text = "produktiv"
    37. Else
    38. frm_main.lbl_produktiv54.Text = "Störung"
    39. End If
    40. '----------------------------------------------------------------------------------------------------------------
    41. 'FA auslesen und anzeigen
    42. Dim FA As String
    43. xml_Doc.LoadXml(XMLString) ' ... XML-Datei aus String laden
    44. xml_Knoten = xml_Doc.SelectSingleNode("/bde/fertigungsauftrag") ' Mit XPath ab Anfang zum gesuchten Konten gehen
    45. FA = Mid(xml_Knoten.InnerText, 6, 5)
    46. frm_main.lbl_fa54.Text = FA
    47. '----------------------------------------------------------------------------------------------------------------
    48. 'Auflage Stck. auslesen
    49. xml_Doc.LoadXml(XMLString) ' ... XML-Datei aus String laden
    50. xml_Knoten = xml_Doc.SelectSingleNode("/bde/application/auflage") ' Mit XPath ab Anfang zum gesuchten Konten gehen
    51. frm_main.lbl_auflage54.Text = (xml_Knoten.InnerText)
    52. '----------------------------------------------------------------------------------------------------------------
    53. 'Auflage brutto m auslesen
    54. xml_Doc.LoadXml(XMLString) ' ... XML-Datei aus String laden
    55. xml_Knoten = xml_Doc.SelectSingleNode("/bde/application/brutto") ' Mit XPath ab Anfang zum gesuchten Konten gehen
    56. frm_main.lbl_brutto54.Text = (xml_Knoten.InnerText)
    57. 'Maximum des Progressbar auf Bruttometer des FA setzen
    58. Auflage = Convert.ToInt32(xml_Knoten.InnerText)
    59. frm_main.bar_prod54.Maximum = Auflage
    60. '----------------------------------------------------------------------------------------------------------------
    61. 'Gutmeter auslesen und anzeigen
    62. xml_Doc.LoadXml(XMLString) ' ... XML-Datei aus String laden
    63. xml_Knoten = xml_Doc.SelectSingleNode("/bde/laengegut") ' Mit XPath ab Anfang zum gesuchten Konten gehen
    64. frm_main.lbl_metergut54.Text = (xml_Knoten.InnerText)
    65. 'produzierte Gutmeter als Fortschritt% im Progressbar anzeigen und Text als Prozent anzeigen
    66. Gutmeter = Convert.ToInt32(xml_Knoten.InnerText)
    67. frm_main.bar_prod54.Value = Gutmeter
    68. Fortschritt = (Gutmeter * 100) / Auflage
    69. frm_main.lbl_prod54.Text = Fortschritt & "%"
    70. frm_main.lbltest54.Text = Fortschritt
    71. '----------------------------------------------------------------------------------------------------------------
    72. 'Schlechtmeter auslesen und anzeigen
    73. xml_Doc.LoadXml(XMLString) ' ... XML-Datei aus String laden
    74. xml_Knoten = xml_Doc.SelectSingleNode("/bde/laengeschlecht") ' Mit XPath ab Anfang zum gesuchten Konten gehen
    75. frm_main.lbl_meterschlecht54.Text = (xml_Knoten.InnerText)
    76. '----------------------------------------------------------------------------------------------------------------
    77. 'produzierte Druckrollen auslesen
    78. xml_Doc.LoadXml(XMLString) ' ... XML-Datei aus String laden
    79. xml_Knoten = xml_Doc.SelectSingleNode("/bde/mengegut") ' Mit XPath ab Anfang zum gesuchten Konten gehen
    80. frm_main.lbl_drollengut54.Text = (xml_Knoten.InnerText)
    81. End Sub

    ==> seid .net zueinander :D <3 <==

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

    Axxxxxl schrieb:

    VB.NET-Quellcode

    1. xml_Doc.LoadXml(XMLString)
    kommt 8 Mal vor, ein Mal genügt.
    Wenn in den Strings numerische Werte stehen, die auch numerische Werte verkörpern, konvertiere und benutze sie als numerische Werte.
    Und:

    VB.NET-Quellcode

    1. Sub druckmaschinen(ByVal ma_nummer As Integer, ma_text As String, grp_name As String)
    2. If ma_nummer = "54" Then
    ==> Option Strict On.
    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!