Benutzersteuerelement an Sub übergeben

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

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Toolmaster.

    Benutzersteuerelement an Sub übergeben

    Guten Morgen,
    Ich glaube ich habe ein leichtes Anfängerproblem und komme nicht weiter :)

    Hier einmal mein Code

    VB.NET-Quellcode

    1. Private Dieser_PC_Control As New Dieser_PC_Hauptform
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. Kategorie(Dieser_PC_Control)
    4. End Sub
    5. Private Sub Kategorie(ByVal Kategorie_Control_Load As Control)
    6. Kategorie_Control_Load.Location = New Point(0, 59)
    7. Controls.Add(Kategorie_Control_Load)
    8. Kategorie_Control_Load.Load_and_refresh()
    9. Kategorie_Control_Load.Show()
    10. End Sub


    Jetzt zu meinem Problem. Bis auf

    VB.NET-Quellcode

    1. Kategorie_Control_Load.Load_and_refresh()
    funktioniert alles. Das Usercontrol "Dieser_PC_Control" hat eine Public Sub mit dem Namen "Load_and_refresh" die ich mit der genannten fehlerhaften Zeile aufrufen möchte.

    Wo ist mein Denkfehler? Hoffe auf eure Hilfe.

    Grüße Toolmaster
    Dein Funktionsparameter Kategorie_Control_Load ist vom Typ Control, d.h. dem Compiler und dem .NET-Framework ist erstmal nur bekannt, dass das darin referenzierte Objekt ein "Control" ist, aber nicht, zu welcher von Control abgeleiteten Klasse es gehört. Darum kann es die Methode deiner Klasse Dieser_PC_Hauptform nicht finden.
    Wenn du sicher ausschließen kannst, dass deine Methode mit anderen Objekten als solchen von Dieser_PC_Hauptform aufgerufen wird, kannst du dein Objekt auf diesen Typ casten, z.B.

    VB.NET-Quellcode

    1. Dim hf As Dieser_PC_Hauptform = DirectCast(Kategorie_Control_Load, Dieser_PC_Hauptform)
    2. hf.Load_and_refresh()

    Sinnvoller wäre es aber, zuvor zu überprüfen, ob dein Parameter auch wirklich diesen Typ hat oder mit TryCast zu arbeiten.
    Weltherrschaft erlangen: 1%
    Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
    Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
    Danke.
    Aufgrund der Frage gehe ich davon aus, dass es 10 unterschiedliche UCs sind. Dann musst Du wohl eine Basisklasse erstellen, welche die genannte Methode aufweist und alles UCs erben von jener Basisklasse. Der Sub-Parameter ist dann vom Basisklassentyp.
    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.

    Toolmaster schrieb:

    um mehrere Controls anzusprechen
    Welchen Typ haben die Controls?
    Wenn der Typ verschieden ist, frag ihn ab und caste dann richtig:

    VB.NET-Quellcode

    1. Private Sub Kategorie(ByVal Kategorie_Control_Load As Control)
    2. If Kategorie_Control_Load.GetType() Is GetType(Button) Then
    3. MessageBox.Show("Button")
    4. ElseIf Kategorie_Control_Load.GetType() Is GetType(ListBox) Then
    5. MessageBox.Show("ListBox")
    6. End If
    7. End Sub
    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 & @ErfinderDesRades (obwohl Du ja nur einen Verbesserungsvorschlag für RfGs Antwort gabst): Ihr wisst, dass es um UserControls geht?
    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 und?
    Dann steht da halt statt Button => UserControl1
    und statt ListBox => UserControl2.
    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!
    Upsa, ich bin ja selber noch ne Antwwort schuldig.
    @Toolmaster: Mein Gedanke ist folgender:
    CodeFile1:

    VB.NET-Quellcode

    1. Public MustInherit Class BaseUC : Inherits UserControl
    2. Public MustOverride Sub Load_and_refresh()
    3. End Class

    Damit wird eine Basisklasse erstellt, die selber nicht zu einem konkreten Objekt werden kann (dank MustInherit (= muss beerbt werden)) und gleichzeitig wird festgelegt, dass die Klassen, die von dieser Basisklasse erben, eine Prozedur namens Load_and_refresh haben müssen (dank MustOverride)
    Dann erstellst Du 1-2 (oder auch 10) UserControls, gehst in deren Datei .Designer.vb rein und ersetzt die Zeile Inherits System.Windows.Forms.UserControl durch Inherits BaseUC. Danach kannst musst Du noch in die normalen CodeDateien der UserControls eine konkrete Prozedur Load_and_refresh erstellen, die für jedes UC anders sein kann. Fertig. Für den unwahrscheinlichen Fall, dass jene Prozedur für alle UCs identisch sein soll, meld Dich, dann geht es noch etwas einfacher.

    Der weitere Aufruf erfolgt dann im Hauptprogramm über (ich nehm jetzt mal als Beispiel die Sub aus Post#1):

    VB.NET-Quellcode

    1. Private Sub Test()
    2. Kategorie(UserControl1)
    3. Kategorie(UserControl2)
    4. End Sub
    5. Private Sub Kategorie(Kategorie_Control_Load As BaseUC)
    6. Kategorie_Control_Load.Load_and_refresh()
    7. End Sub


    Abhängig davon, wie die Implementierung/Überschreibung von Load_and_refresh in UC1 und UC2 erfolgen, wird jeweils anderer Code ausgeführt.

    EDIT:
    Hab mal ein Beispielprojekt angehangen. Mit MustInherit wird's mit den UC-Designern doch etwas tricky, daher das ganze mal ohne.
    Dateien
    • WindowsApp3.zip

      (40,29 kB, 62 mal heruntergeladen, zuletzt: )
    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.

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

    VaporiZed schrieb:

    Mit MustInherit wird's mit den UC-Designern doch etwas tricky
    Deswegen nimmt man da einfach ein Interface, da geht das ganze wieder sehr einfach:

    VB.NET-Quellcode

    1. Public Class MyUC : Inherits UserControl, Implements ILoad_and_refresh
    2. ' ...
    3. End Class

    VB.NET-Quellcode

    1. Interface ILoad_and_refresh
    2. Sub Load_and_refresh()
    3. End Interface
    Den Rest macht die IDE.
    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!
    Ah, ok. Ist zwar nicht mein Thread hier. Aber wieder was dazugelernt.
    Das kommt davon, wenn man bisher noch nie mit Interfaces rumhantiert hat.
    Ich weiß zwar nicht, ob das jetzt VS-versionsabhängig ist, aber bei VS2017 muss ich Inherits und Implements per : trennen:

    VB.NET-Quellcode

    1. Public Class MyUC : Inherits UserControl: Implements ILoad_and_refresh

    Für den Fall, dass der TE drüber stolpern soll. Sonst kommt:

    Visual Studio Debugger schrieb:


    Fehler BC30121 In einer Class-Anweisung darf "Inherits" nur einmal verwendet werden und kann nur eine Klasse angeben.


    EDIT: Und als Parameter im Hauptprogramm wird dann ein Objekt übergeben, welches jene Schnittstelle implementiert. In der Prozedur ist der Parameter wiederum nur vom Schnittstellentyp:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. GeneralLoadAndRefreshProcedure(UserControl11)
    3. GeneralLoadAndRefreshProcedure(UserControl21)
    4. End Sub
    5. Private Sub GeneralLoadAndRefreshProcedure(ObjectWithInterface As ILoadAndRefresh)
    6. ObjectWithInterface.Load_and_refresh()
    7. End Sub

    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.

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

    VaporiZed schrieb:

    aber bei VS2017 muss ich Inherits und Implements per : trennen:
    Das sollte in VB.NET einheitlich sein, ich hab da an die C#-Komma-Syntax gedacht. :D
    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!