Funktion aus übergeordnetem Formular aufrufen

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

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

    Funktion aus übergeordnetem Formular aufrufen

    Hallo,

    ich habe ein Formular mit einer Funktion, die eine Oberfläche zeichnet. Über einen Menüpunkt kann ein weiteres Formular geöffnet werden. In dem zweiten Formular können Einstellungen vorgenommen werden.

    Ich möchte, daß, wenn die Einstellungen geändert werden, eine Funktion aus dem übergeordneten Formular ausgeführt wird, um die Grafische Darstellung in echtzeit zu aktualisieren.

    Leider kann ich aus dem zweiten Formular heraus keine Funktionen aus dem Hauptformular heraus aufrufen. Kann mir jemand bei meinem Problem helfen?

    Vielen Dank schon mal im Voraus.
    @SpaceyX Jou.
    @tron25 Gugst Du hier unter Punkt 1.
    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!
    Danke für den Link. Den Beitrag hatte ich gestern auch schon gelesen. Leider habe ich das problem, daß ich die Beispielbilder nicht erkennen kann. Könntest du mir bitte die Sache mit dem Eventhandler in Klartext schreiben?

    Um es zu konkretisieren, würde ich vorschlagen, daß wir von folgenden Voraussetzungen ausgehen:

    Form1 hat eine Funktion, namens "GrafikAufbauen"
    Form2 hat die Funktion "Aktualisieren", welche die Funktion "GrafikAufbauen" aufrufen soll
    Form2 soll nicht-modal aufgerufen werden, damit mann immer wieder zu Form1 wechseln kann, um die Änderungen betrachten zu können.

    P.S.: Sorry für den Themenumschwung, aber kann mir Jemand sagen, wie ich Beiträge aus dem Forum entfernen kann? Ich war etwas zu voreilig und habe heute Morgen einen zweiten Beitrag mit dem gleichen Thema geschrieben. Da doppelte Beiträge das Forum nur zumüllen, würde ich diesen gerne wieder löschen.
    Hallo @tron25!

    Wegen deines Projektes: Hier brauchst du eingelich keine Eventhandler. Der Schlüssel zur Lösung heißt Interface!

    Hab dir hier jetzt mal was Qick'n'Diry hingeschrieben (funktioniert auch :D):

    VB.NET-Quellcode

    1. Public Interface IMyForm
    2. Sub ReDraw(einstellungen As Einstellungen)
    3. End Interface
    4. Public Class ZweiteForm
    5. Private aufrufendeForm As IMyForm
    6. Private einstellungen As Einstellungen
    7. Public Sub New(creator As IMyForm)
    8. InitializeComponent()
    9. Me.aufrufendeForm = creator
    10. Me.einstellungen = New Einstellungen()
    11. End Sub
    12. Private Sub EinstellungeGeaendert()
    13. Me.aufrufendeForm.ReDraw(einstellungen)
    14. End Sub
    15. Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
    16. Me.einstellungen.Wert1 = Me.TextBox1.Text
    17. Me.EinstellungeGeaendert()
    18. End Sub
    19. Private Sub NumericUpDown1_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown1.ValueChanged
    20. Me.einstellungen.Wert2 = Me.NumericUpDown1.Value
    21. Me.EinstellungeGeaendert()
    22. End Sub
    23. End Class
    24. Public Class Form1
    25. Implements IMyForm
    26. Private einstellungen As Einstellungen
    27. Private zweiteForm As Form
    28. Public Sub New()
    29. InitializeComponent()
    30. Me.einstellungen = New Einstellungen()
    31. Me.zweiteForm = New ZweiteForm(Me)
    32. End Sub
    33. Public Sub ReDraw(einstellungen As Einstellungen) Implements IMyForm.ReDraw
    34. Me.einstellungen = einstellungen
    35. Me.TextBox1.Text = Me.einstellungen.Wert1
    36. Me.NumericUpDown1.Value = Me.einstellungen.Wert2
    37. End Sub
    38. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    39. Me.zweiteForm.ShowDialog()
    40. End Sub
    41. End Class
    42. Public Class Einstellungen
    43. Public Property Wert1 As String
    44. Public Property Wert2 As Integer
    45. End Class


    Du musst dir im Prinzip nur zwei Forms machen, die Hauptform lässt du das Interface implementieren. Der zweiten Form gibst du beim Erstellen eine Referenz auf die Hauptform mit, sodass du in der zweiten Form im Falle einer Aktualisierung von Einstellungen auf der Hauptform ein Re-Draw auslösen kannst - also dafür sorgen kannst, dass die Hauptform weiß, WANN sie sich neu zeichnen soll und WAS/WIE sie neu zeichnen soll.

    Hoff ich konnte helfen
    Lg Radinator
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    @Radinator What :?:
    Da kannst Du Dir auch gleich die aufrufende Form als Instanz von Form1 merken und das Interface sparen, dann wäre der Code übersichtlicher.
    Letztenendes ruft bei Dir Form1 Form2 auf und außerdem ruft Form2 Form1 auf.
    Genau dies wollen wir durch Verwendung von Events vermeiden, das ist in anständigen Design-Spezifikationen ein No Go.
    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!

    RodFromGermany schrieb:

    dann wäre der Code übersichtlicher.
    Ja

    RodFromGermany schrieb:

    aufrufende Form als Instanz von Form1 merken
    Mach ich doch, nur halt ned als Referenz auf eine Form sondern auf IMyForm

    RodFromGermany schrieb:

    Interface sparen
    Nö. Das Interface ist ja genau dazu da, dass ich auf der Form1 das ReDraw aufrufen kann, welches Form1 dann selbser definieren kann. Wie soll ich von Form2 denn bitte sonst auf Form1 einwirklen und es dir Grafik neu zeichnen lassen?
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    @tron25nullIch hab Dir ein kleines Beispielprojekt hier angehängt.

    WindowsApplication50.zip

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private WithEvents _settings As New Settings
    3. Private Sub _settings_SettingsChanged(sender As Object, e As EventArgs) Handles _settings.SettingsChanged
    4. Me.Invalidate()
    5. End Sub
    6. Protected Overrides Sub OnPaint(e As PaintEventArgs)
    7. e.Graphics.DrawLine(New Pen(_settings.LineColor, 10), 10, 10, 10, _settings.LineLenght)
    8. MyBase.OnPaint(e)
    9. End Sub
    10. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    11. _settings.Show()
    12. End Sub
    13. End Class


    VB.NET-Quellcode

    1. Public Class Settings
    2. Public Event SettingsChanged As EventHandler
    3. Public Property LineLenght As Single
    4. Public Property LineColor As Color
    5. Public Sub New()
    6. InitializeComponent()
    7. Me.txtLineLength.Text = "10"
    8. Me.LineLenght = 10.0F
    9. Me.cmbLineColor.Items.AddRange([Enum].GetNames(GetType(KnownColor)))
    10. Me.cmbLineColor.SelectedIndex = 0
    11. Me.LineColor = Color.FromName(Me.cmbLineColor.Items(0).ToString())
    12. End Sub
    13. Private Sub btn_ApplySettings_Click(sender As Object, e As EventArgs) Handles btn_ApplySettings.Click
    14. Me.LineLenght = Convert.ToSingle(Me.txtLineLength.Text)
    15. Me.LineColor = Color.FromName(Me.cmbLineColor.SelectedItem.ToString())
    16. OnSettingsChanged(EventArgs.Empty)
    17. End Sub
    18. Protected Overridable Sub OnSettingsChanged(e As EventArgs)
    19. RaiseEvent SettingsChanged(Me, e)
    20. End Sub
    21. Protected Overrides Sub OnFormClosing(e As FormClosingEventArgs)
    22. e.Cancel = True
    23. Me.Hide()
    24. MyBase.OnFormClosing(e)
    25. End Sub
    26. End Class


    Du erstellst Dir eine Form "Settings" oder wie immer Du sie auch nennen willst. In dieser Form (Klasse) definierst Du ein Event SettingsChanged (oder wie auch immer).

    VB.NET-Quellcode

    1. Public Event SettingsChanged As EventHandler


    In Deiner Hauptform erzeugst Du eine Instanz Deiner SettingsFrom

    VB.NET-Quellcode

    1. Private WithEvents _settings As New Settings


    Das Schlüsselwort hier ist "WithEvents". Dies ermöglicht es Dir, im CodeEditor auf die Events der SettingsForm zuzugreifen. Alternativ ginge auch das Einhängen in ein Event mit "AddHandler".



    Das festgelegte Event "SettingsChanged" wird ausgelöst, nachdem in der SettingsForm der Button "btnApplySettings" betätigt wurde:

    VB.NET-Quellcode

    1. Private Sub btn_ApplySettings_Click(sender As Object, e As EventArgs) Handles btn_ApplySettings.Click
    2. Me.LineLenght = Convert.ToSingle(Me.txtLineLength.Text)
    3. Me.LineColor = Color.FromName(Me.cmbLineColor.SelectedItem.ToString())
    4. OnSettingsChanged(EventArgs.Empty)
    5. End Sub
    6. Protected Overridable Sub OnSettingsChanged(e As EventArgs)
    7. RaiseEvent SettingsChanged(Me, e)
    8. End Sub


    Das Schlüsselwort hierfür ist "RaiseEvent". Du musst das Auslösen nicht in eine extra Prozedur auslagern, falls Du Dich das fragst. Dies hat im Grunde nur Relevanz, wenn Du Deine SettingsForm vererbst.

    Im Beispielprojekt wird in der SettingsForm festgelegt, welche Länge und Farbe eine Linie haben soll.

    Falls Du Fragen hast, jederzeit.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

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

    Allgemeine Anmerkung: Crossreferenzen wie Me.zweiteForm = New ZweiteForm(Me), die die eigene Instanz weitergeben, sind häufig einer von mehreren Indikatoren für ein suboptimales Anwendungsdesign.

    @SpaceyX: Ich würde OnSettingsChanged mit Parameter definieren, d.h. so:

    VB.NET-Quellcode

    1. Protected Overridable Sub OnSettingsChanged(e As EventArgs)
    2. RaiseEvent SettingsChanged(Me, e)
    3. End Sub

    ...und die Methode entsprechend mit EventArgs.Empty verwenden.
    Gruß
    hal2000
    Vielen Dank für die zahlreichen Antworten. Ich werde mir das Beispielprogramm und die Codebeispiele genauer anschauen. Allerdings ist mein Code nicht so kompliziert. Ich versuche es mal zu verdeutlichen:

    Im Hauptformular, "PunktBilderFormular", wird eine Grafik aus Braillepunkten erzeugt. Dafür gibt es ein zweidimmensionales Array, "PunktBildArray", in dem die Werte für die einzelnen Braillepunkte stehen. Das Array ist global. Desweiteren gibt es ein Fokusrechteck, welches in seiner Position und Größe verändert werden kann. Über mehrere Menüpunkte können unterschiedliche Formen, wie z.B. Rechtecke, Dreiecke, Linien usw. gezeichnet werden. Das Fokusrechteck bezieht seine Braillepunkte ebenfalls aus einem Array, "FokusArray". Erst, wenn der Benutzer mit Enter bestätigt, werden die Werte aus FokusArray in PunktBildArray übertragen. Jedesmal, wenn etwas neues gezeichnet wird, wird die entsprechende Form mit den Parametern des Fokusrechtecks in ein weiteres Array "ObjektKatalogListe", eingetragen. Die Funktion "GrafikAufbauen" zeichnet anhand von "PunktBildArray" den Arbeitsbereich. Im zweiten Formular wird eine Liste der bis dahin erzeugten Elemente angezeigt. Die Liste bezieht seine Einträge aus "ObjektkatalogListe". Jeder Eintrag enthält zusätzlich noch eine Checkbox. Über diese kann bestimmt werden, ob dieses Objekt gezeichnet oder ausgelassen wird. Zudem besitzt jedes Element mehrere Parameter, die das Aussehen und die Position bestimmen. Diese Werte können ebenfalls geändert werden. Beim Aufruf des zweiten Formulares wird eine Kopie von "PunktBildArray" erstellt. Wenn die Schaltfläche "Abbrechen" gedrückt wird, wird die Kopie wieder zurückgeschrieben, ansonsten werden die Änderungen beibehalten.

    Nun möchte ich, daß, wenn mann einen Eintrag aus der Objektliste auscheckt, die Parameter ändert oder entfernt, die Funktion "GrafikAufbauen" im Hauptformular aufgerufen wird. Dadurch, daß die Änderungen direkt in "PunktBildArray" geschrieben werden, muß das zweite Formular keine Parameter an das Erste übergeben. "PunktBildArray" ist in einem Modul deklariert.

    Ich hoffe, daß ich den Sachverhalt verständlich beschrieben habe.

    Hier noch ein Link zur alten Version meines Programms:

    @tron25 Nach einer Änderung von Properties musst Du die relevanten Controls invalidisieren.
    Das System ruft daraufhin die Paint-Routine auf und alles wird neu gezeichnet.
    Dies setzt voraus, dass Du Deine Darstellung über den Paint-Mechanismus realisierst.
    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 mache es nicht über das Paint-Ereignis, sondern über die Funktion "GrafikAufbauen". Ich brauche nur die Möglichkeit, eine Funktion aus dem Hauptformular aufrufen zu können, ganz ohne Parameterübergabe.

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

    @tron25 Sende ein Event, das hatten wir grade.
    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!
    Vielen Dank, aber ich habe es doch anders gelöst. Normalerweise ist es ja so, daß, wenn man einen Formularnamen schreibt, eine Liste mit den verfügbaren Funktionen aufgelistet wird. Allerdings geschieht das nicht, wen man einen übergeordneten Formularnamen schreibt. Wenn man nach dem "." einen Funktionsnamen schreibt, wird diese dennoch aufgerufen.

    tron25 schrieb:

    Normalerweise ist es ja so, daß, wenn man einen Formularnamen schreibt, eine Liste mit den verfügbaren Funktionen aufgelistet wird.
    Das ist VB6-Kompatibilitäts-Ranz.
    Gugst Du hier.
    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!