ToolStripMenuItem als Form Parameter übergeben

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

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    ToolStripMenuItem als Form Parameter übergeben

    Hi,

    ich habe eine Form mit einem Tool Strip. Ein bestimmtes Menu Item kann unter bestimmten Bedingungen aktiv sein, dann wird es rot eingefärbt. Wenn es nicht aktiv ist, hat es die schwarze Standard Farbe.

    Die Form kann in beliebig vielen Instanzen geöffnet sein. Die Forms merke ich mir in Openform, das ist eine List (of Form). Die Färbung soll dann in allen Instanzen eingetragen werden.

    So habe ich das gelöst:

    VB.NET-Quellcode

    1. Private Sub ColorMenuItem(blnActive As Boolean)
    2. Dim myColor As Color = SystemColors.ControlText
    3. If blnActive Then myColor = Color.Red
    4. For Each myForm In OpenForms
    5. If myForm Is Nothing Then Continue For
    6. myForm.CopyAreaToolStripMenuItem.ForeColor = myColor
    7. Next
    8. End Sub


    Von dieser Lösung war ich so begeistert, dass ich das nun für andere MenuItems auch so lösen will. Und natürlich möchte ich das mit einer einzigen Prozedur lösen, mit anderen Worten, das MenuItem soll variabel sein.

    So habe ich das versucht:

    VB.NET-Quellcode

    1. Private Sub ColorMenuItem(myToolStripMenuItem As ToolStripMenuItem, blnActive As Boolean)
    2. Dim myColor As Color = SystemColors.ControlText
    3. If blnActive Then myColor = Color.Red
    4. For Each myForm In OpenForms
    5. If myForm Is Nothing Then Continue For
    6. myForm.myToolStripMenuItem.ForeColor = myColor
    7. Next
    8. End Sub


    Fehler BC30456 "myToolStripMenuItem" ist kein Member von "Form1".

    So klappt das also nicht ! Obwohl es gut aussieht. :)

    Hat jemand eine Ahnung wie ich das hinbekommen kann ?

    LG
    Peter

    Peter329 schrieb:

    OpenForms
    sollte ausschließlich Items enthalten, die nicht Nothing sind.
    Die Member von OpenForms sind allerdings vom Typ Form, die musste dann noch auf Deine FormX casten:

    VB.NET-Quellcode

    1. Dim frm = CType(myForm, FormX)
    2. frm.myToolStripMenuItem.ForeColor = myColor
    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!
    Meine OpenForm sieht wie folgt aus:

    VB.NET-Quellcode

    1. Public OpenForms As New List(Of frmDeskTopCalculator)


    Die Member können schon "nothing" werden. Jede neue Form, die ich öffne, hängt sind an die OpenForm Liste an Und im FormClosing wird der Eintrag auf "nothing" gesetzt. Dadurch erhält jede Form eine eindeutige fortlaufende Nummer, die dem Index von OpenForm entspricht.

    Die Sache mit dem CTypeklappt leider nicht:

    VB.NET-Quellcode

    1. Private Sub ColorMenuItem(myToolStripMenuItem As ToolStripMenuItem, blnActive As Boolean)
    2. Dim myColor As Color = SystemColors.ControlText
    3. If blnActive Then myColor = Color.Red
    4. For Each myForm In OpenForms
    5. If myForm Is Nothing Then Continue For
    6. 'myForm.ColorMenuItem(myToolStripMenuItem, myColor) '<---- das funktioniert (expliziter FormName) (ist aber nicht das was ich will)
    7. 'myForm.myToolStripMenuItem.ForeColor = myColor '<---- das funktioniert nicht (FormName als Parameter)
    8. 'myToolStripMenuItem.ForeColor = myColor '<---- das funktioniert (Form Name als Parameter ohne Form als Prefix (ist aber nicht das was ich will)
    9. Dim frm = CType(myForm, frmDeskTopCalculator)
    10. frm.myToolStripMenuItem.ForeColor = myColor '<---- und das funktioniert auch nicht
    11. Next
    12. End Sub


    BC30456 "myToolStripMenuItem" ist kein Member von "frmDeskTopCalculator".

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Peter329“ ()

    @Peter329 Meine OpenForms sind Member von Application: :thumbsup:

    VB.NET-Quellcode

    1. Application.OpenForms
    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!
    guck mal im Designer die myToolStripMenuItem.Modifyers - Property an. Vlt. muss die auf Friend oder Public gestellt wern.

    Und was tut deine Methode mit dem myToolStripMenuItem - Argument (ausser Verwirrung stiften)?

    edit - ja, und was Rod anspricht: Keine gute Idee, deine Openforms genauso zu benennen, wie die Openforms, die's schon gibt (Confusion rulz).
    Ok, da war OpenForms keine gute Idee. Das Dingens heißt jetzt bei mir OpenFormList. Damit ist die Namenskollision erst mal behoben.

    Vermutlich brauche ich gar keine eigene Liste, weil es ja schon die Application.OpenForms gibt. Aber zielgerichtet wie ich nun mal bin, werde ich mich damit später beschäftigen. :)

    Und was tut deine Methode mit dem myToolStripMenuItem - Argument (ausser Verwirrung stiften)?


    Na ja, es ist halt immer schwer, ein Anliegen so richtig verständlich zu machen. Ich versuche es mal auf andere Weise. So sieht mein Coding jetzt aus:

    VB.NET-Quellcode

    1. Private Sub ColorCopyAreaItem(blnActive As Boolean)
    2. Dim myColor As Color = SystemColors.ControlText
    3. If blnActive Then myColor = Color.Red
    4. For Each myForm In OpenFormList
    5. If myForm Is Nothing Then Continue For
    6. myForm.CopyAreaToolStripMenuItem.ForeColor = myColor
    7. Next
    8. End Sub
    9. Public Sub ColorClipboardItem(blnActive As Boolean)
    10. Dim myColor As Color = SystemColors.ControlText
    11. If blnActive Then myColor = Color.Red
    12. For Each myForm In OpenFormList
    13. If myForm Is Nothing Then Continue For
    14. myForm.ClipToolStripMenuItem.ForeColor = myColor
    15. myForm.ShowToolStripMenuItem.Enabled = blnActive
    16. Next
    17. End Sub


    Die beiden Routinen sind bis auf das unterschiedliche ToolStripMenuItem fast identisch. Diese beiden Routinen würde ich gern zusammenfassen.

    Normalerweise würde ich eine Sub schreiben und das ToolStripMenuItem als Parameter übergeben.

    Hier klappt das aber nicht ! Weil der Parameter noch den Prefix myForm erhält. Dann wird nämlich der PARAMETERNAME in myForm gesucht. Und den gibt es da nicht !

    Habe ich jetzt mein Problem verständlich machen können ?

    Ich bin fast der Meinung, dass dies nicht zu realisieren ist. Was natürlich schade wäre. Aber vielleicht hat jemand ja doch noch eine zündende Idee.

    LG
    Peter

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

    Unterschiedliche Dinge unterscheiden - benamung hilft dabei

    VB.NET-Quellcode

    1. Public Sub ColorClipboardItem(showToolActive As Boolean, copyAreaActive As Boolean)
    2. Dim showToolColor = If(showToolActive, Color.Red, SystemColors.ControlText)
    3. Dim copyAreaColor = If(copyAreaActive, Color.Red, SystemColors.ControlText)
    4. For Each myForm In OpenFormList
    5. If myForm Is Nothing Then Continue For
    6. myForm.ClipToolStripMenuItem.ForeColor = showToolColor
    7. myForm.ShowToolStripMenuItem.Enabled = showToolActive
    8. myForm.CopyAreaToolStripMenuItem.ForeColor = copyAreaColor
    9. Next
    10. End Sub

    Na gut, jetzt behandelst du beide ToolStripMenuItems explizit in einer Routine. Und damit vermeidest du die Parameterübergabe.

    So richtig happy bin ich damit nicht. Denn an der Stelle, wo ich etwa das ClipToolStripMenuItem behandle, habe ich die Bedingung für das Setzen des CopyAreaToolStripMenuItem nicht mehr parat. Das müsste ich neu ermitteln, bzw mir copyAreaActive irgendwo merken.

    Für zwei Items mag das ja noch akzeptabel sein. Aber was ist, wenn ich nicht zwei sondern 10 MenuItems dieser Art habe ? Wenn sich jetzt ein Item ändert, dann werden die übrigen neun Items in allen Forms vollkommen unnötig noch einmal überprüft.

    Man kann das machen. Aber das ist halt nicht so sehr eine Lösung, des Problems der Addressierung, sondern eher eine Umgehung.

    In der Prozedursprache REXX (die läuft vor allem unter zOS auf dem IBM Host), gibt es den INTERPRET Befehl. Da kann man im Programm eine Source Code Anweisung zusammenbasteln und diese dann dynamisch ausführen lassen. So etwas scheint in VB nicht zu existieren.

    Trotzdem, Danke für dein Code Beispiel !

    LG
    Peter

    Peter329 schrieb:

    In der Prozedursprache REXX (die läuft vor allem unter zOS auf dem IBM Host), gibt es den INTERPRET Befehl. Da kann man im Programm eine Source Code Anweisung zusammenbasteln und diese dann dynamisch ausführen lassen. So etwas scheint in VB nicht zu existieren.
    Ähm - solchen Laufzeit-generierten-Code würdest du aber sicher nicht gerne debuggen wollen - oder hat die Interpreterei Exceptions, Codestop, Haltepunkt, Lokalfenster, Überwachungsfenster?

    Ich bin gottfroh, dass der Code, den ich schreibe so bleibt wie ich ihn geschrieben habe.
    Ich bin gottfroh, dass der Code, den ich schreibe so bleibt wie ich ihn geschrieben habe.


    Da bin ich ja auch heilfroh drüber ! Da sind wir uns doch vollkommen einig. :)

    Also, dann nehme ich jetzt aus der Diskussion mit, dass man ein Control nicht als Parameter übergeben kann, wenn der den Prefix von mehreren Forms erhalten soll.

    Das kann man nur umgehen, indem man auf irgend eine Weise die Parameter Übergabe vermeidet.

    Diese Art von Problemstellung kommt ja nicht gar so oft vor und deshalb kann ich damit leben. Ich wollte halt sicherstellen, dass ich nicht irgend eine naheliegende Feature des VB übersehe, ehe ich Code dupliziere.

    LG
    Peter
    @Peter329 Jetzt hab ich iwie den Faden verloren.
    Kannst Du Dein Problem aus jetziger Sicht noch mal formulieren?
    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!
    @RFG

    Na in Post #6 habe ich doch mein Problem dargestellt.

    EDR hat in Post #7 eine Lösung eingestellt, die zwar funktioniert aber das Problem m.E. eher umgeht.

    Die Frage die ungelöst ist: wie kann man die beiden Prozeduren aus Post #6 durch eine einzige Prozedur ablösen, wo wobei die Übergabe der Controls als PARAMETER erfolgen soll.

    LG
    Peter

    Peter329 schrieb:

    aber das Problem m.E. eher umgeht.
    Ich sehe in Post #6 kein Problem. Wenn der Aufrufparameter beider Prozeduren contextabhängig, aber identisch ist, hast Du doch die Lösung im Code von Post #7.
    Ansonsten verstehe ich Dein Problem nicht. Sorry.
    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 schrieb:

    Das ergibt doch gar keinen Sinn.
    Angenommen 7 Forms in der OpenformsList - willst du dann 7 MenuItems als Parameter übergeben, oder gar 14 - weil scheint sich ja um zweierlei MenuItems zu handeln, je Form?


    Waaaaaa ... ! Natürlich will ich nur EINEN Parameter übergeben.

    EINE Bedingung ändert sich. Und dann will genau das dazu PASSENDE MenuItem in allen Forms ändern. Und dieses Menu Item übergebe ich als Parameter myToolStripMenuItem. Die Forms sind alle Instanzen der GLEICHEN Klasse. Und deshalb haben die Menu Items auch alle die gleichen Namen.

    VB.NET-Quellcode

    1. Private Sub ColorMenuItem(myToolStripMenuItem As ToolStripMenuItem, blnActive As Boolean)


    Ich gebe es jetzt auf. Manchmal ist das schon sehr schwierig ein Anliegen transparent zu machen.

    Trotzdem finde ich das sehr nett, dass ihr euch mit meinem Problem befasst habt. Ich meine jetzt einiges über die Art der Addressierung im VB besser zu verstehen als vorher. Auch wenn ich nicht die Lösung zu meinem Problem gefunden habe. Aber ich habe ja eine funktionierende Umgehung. Und die muss es dann auch tun.

    Vielen Dank ! Daumen hoch ! Und Problem abgeschlossen ! :)

    LG
    Peter

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

    @Peter329 Deine Herangehensweise halte ich für die weniger gute.
    Üblicherweise wird das ja auf mehrere Items angewendet, Tendenz: Anzahl steigend.
    Nun hast Du die Möglichkeit, in eineer Schleife eine Liste abzuarbeiten, da wird dann einfach ein neues Item dazugeschrieben.
    Oder
    Du fügst einen neuen Aufruf Deiner Routine hinzu.
    Ist im Prinzip äquivalent, Dein Code hat aber einen größeren Overhead.
    ====
    Wenn Du Dir eine gemeinsame Basisklasse oder ein interface erstellst und dies auf Deine Forman anwendest, ist im Parametersatz nur noch ein Boolean, nicht aber ein Item drinne, das kennt dann die Form alleine, wie es sich gehört.
    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!

    Peter329 schrieb:

    Und deshalb haben die Menu Items auch alle die gleichen Namen.
    Dann übergib halt diesen Namen (aber nicht "das Menuitem"). Wo Problem?

    Wie gesagt: "das MenuItem" gibt es nicht - bei 7 Forms sinds 7 MenuItem, zuzüglich dessen, was du übergibst (was aber garnet gefärbt werden soll (oder doch?)) - also 8. Wundert dich das wirklich, das der Gedanke schwer nachvollziehbar ist?

    Von Basisklasse, Interface tätich abraten. Das vereinfacht nix, schafft aber zusätzliche Abhängigkeiten.