Der Verweis auf einen nicht freigegebenen Member erfordert einen Objektverweis.

  • VB.NET

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

    Der Verweis auf einen nicht freigegebenen Member erfordert einen Objektverweis.

    Hallo zusammen,

    ich habe ein kleines Prg geschrieben in welchem ich in einer Klasse ControlService ein Contol (einen Button) dynamisch erstelle.
    In Form1_Load rufe ich die Function SetButton um den Button zu erzeugen und auf der Form anzuzeigen.
    Ich bekomme aber ständig den Fehler: Der Verweis auf einen nicht freigegebenen Member erfordert einen Objektverweis. ;(


    ControlService

    VB.NET-Quellcode

    1. Imports System.Windows.Forms.Control
    2. Public Class ControlService
    3. Private WithEvents CmdButton As Button
    4. Public Sub SetButton(pName As String, pText As String, pLeft As Integer, pTop As Integer,
    5. pHeight As Integer, pWidth As Integer)
    6. Dim CmdButton = New Button
    7. With CmdButton
    8. .Name = pName
    9. .Text = pText
    10. .Left = pLeft
    11. .Top = pTop
    12. .Height = pHeight
    13. .Width = pWidth
    14. Controls.Add(CmdButton)
    15. End With
    16. End Sub
    17. End Class



    Form1_Load

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. Dim Ctrl As ControlService
    4. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5. Ctrl.SetButton("CmdFunction", "Function", 15, 60, 31, 100)
    6. End Sub
    7. End Class


    Könnt Ihr mir da weiterhelfen? ?(

    Vielen Dank für Eure Zeit und Mühe vorab! :)

    Viele Grüße,
    Duster

    P.S.: Ich habe der Einfachheit halber das ganze kleine Projekt angehängt!
    Dateien
    • Source.zip

      (47,68 kB, 8 mal heruntergeladen, zuletzt: )
    Ja, schreibst, das ist die Deklaration, als WAS ist die Variable Ctr.
    Eine Instanz erstellst Du mit New... also New ControlService
    Kannst Du dann auch in einem schreiben, also

    VB.NET-Quellcode

    1. ​Dim Ctr As ControlServie = New ControlService
    "Hier könnte Ihre Werbung stehen..."

    Duster schrieb:

    VB.NET-Quellcode

    1. Controls.Add(CmdButton)
    Controls ist nicht definiert, Du meinst sicher die Me.Controls in einer Form, Deine Klasse ist aber keine Form,
    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).
    VB-Fragen über PN / Konversation werden ignoriert!
    Da wollte ich drauf hinaus.
    Du willst also den Button zu den Form1 Controls hinzufügen.
    Das mach aber bitte nicht in der Klasse ControlService.
    die Sub ist in einer extra Klasse überflüssig wenn nur diese Sub in der Klasse ist.
    Andernfalls würde ich eine Funktion draus machen, die den erstellten Button zurück gibt.
    das kannst du dann in der Form1 den Me.Controls hinzufügen.
    "Hier könnte Ihre Werbung stehen..."
    Dein Formular verwendet die ControlService-Klasse, um etwas zu machen. Das Form ist also der Erschaffer und Besitzer des ControlService-Klassenobjektes. Anders ausgedrückt: Das ControlService-Objekt wird von jemandem genutzt, nämlich dem Form. Und das sollte Dein Gedankengang sein, wer was von wem weiß. Das Form kennt die Details des ControlService-Objektes. Aber das ControlService-Objekt darf nicht wissen, von wem es genutzt wird. Daher darf die ControlService-Klasse nicht Form1 direkt manipulieren, sondern soll nur dafür sorgen, dass sich Form1 selber (mithilfe der ControlService-Klasse) manipuliert/ändert.
    Allgemein: Es gibt Besitzer eines Objektes (das ist bei Dir Form1) und Besitz, also jenes Objekt selbst (ControlService-Klasseninstanz)*. Der Besitzer darf mit seinem Besitz machen, was der will. Der Besitz darf mit seinem Besitzer nicht machen, was er will.

    * Das hast Du selber festgelegt: Post#1, Codeblock#2, Zeile#4: Form1 besitzt ein Objekt vom Typ ControlService.
    Würdest Du hingegen in der ControlService-Klasse sagen: Dim Form As (New) Form1, würde die ControlService-Klasse(ninstanz) ein Form1-Objekt besitzen und könnte mit dem machen, was es will.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    @VaporiZed
    Gut ich verstehe theoretisch vorauf Du hinaus willst.
    Dann ist es so dass die Formklasse der Besitzer der ControlServiceklasee ist und zwar durch

    VB.NET-Quellcode

    1. Dim Ctrl As ControlService = New ControlService
    .
    Die ControlServiceklasse nutzt aber den Besitzer (die Formklasse) durch

    VB.NET-Quellcode

    1. Form1.Controls.Add(CmdButton)
    .

    Das soll so nicht sein, verstehe ich auch aber wie ändere ich das praktisch?

    Hast Du das so gemeint:

    Form_Load:

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. Dim Ctrl As ControlService = New ControlService
    4. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5. Ctrl.SetButton("CmdFunction", "Function", 350, 100, 30, 100, Me)
    6. Ctrl.SetButton("CmdSub", "Sub", 350, 180, 30, 100, Me)
    7. Ctrl.SetButton("CmdSubByRef", "Sub (ByRef)", 325, 260, 30, 150, Me)
    8. 'Ctrl.SetTextBox("TxtBox_01", " ", 100, 100, 80, 200)
    9. End Sub
    10. End Class



    ControlService:

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Imports System.Windows.Forms.Control
    3. Public Class ControlService
    4. #Region "BUTTON"
    5. Public Sub SetButton(pName As String, pText As String, pLeft As Integer, pTop As Integer,
    6. pHeight As Integer, pWidth As Integer, Form As Form)
    7. Dim CmdButton = New Button
    8. With CmdButton
    9. .Name = pName
    10. .Text = pText
    11. .Left = pLeft
    12. .Top = pTop
    13. .Height = pHeight
    14. .Width = pWidth
    15. Form.Controls.Add(CmdButton)
    16. End With
    17. AddHandler CmdButton.Click, AddressOf CmdButton_Click
    18. End Sub
    19. #End Region
    20. #Region "TEXTBOX"
    21. Public Sub SetTextBox(pName As String, pText As String, pLeft As Integer, pTop As Integer,
    22. pHeight As Integer, pWidth As Integer)
    23. Dim TxtBox = New TextBox
    24. With TxtBox
    25. .Name = pName
    26. .Text = pText
    27. .Left = pLeft
    28. .Top = pTop
    29. .Height = pHeight
    30. .Width = pWidth
    31. Form1.Controls.Add(TxtBox)
    32. End With
    33. End Sub
    34. #End Region
    35. #Region "EVENTS"
    36. Sub CmdButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    37. 'Form1.TxtBox.Text = "Test"
    38. End Sub
    39. #End Region
    40. End Class


    Vielen Dank für Deine Mühe!


    Viele Grüße,
    Duster

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

    Das ist eine Möglichkeit, richtig. Ansonsten wie MichaHo schrieb: SetButton zu einer Function machen, die den neuen Button zurückgibt und Form1 fügt den neuen Button selber zu den eigenen CEs hinzu.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    @VaporiZed 2.Möglichkeit:

    In der Zeile 9 der Form Load

    VB.NET-Quellcode

    1. contr = Ctrl.SetButton("CmdFunction", "Function", 350, 100, 30, 100)

    bekomme ich aber nun folgende Fehlermeldung:
    Option Strict On" lässt keine impliziten Konvertierungen von "Object" in "Control" zu.

    Wie kann ich das lösen zumal ich doch immer den Typ Control nutze und nicht den allgemeinen Typ Object?

    ControlService:

    VB.NET-Quellcode

    1. Public Function SetButton(pName As String, pText As String, pLeft As Integer, pTop As Integer,
    2. pHeight As Integer, pWidth As Integer)
    3. Dim CmdButton = New Button
    4. With CmdButton
    5. .Name = pName
    6. .Text = pText
    7. .Left = pLeft
    8. .Top = pTop
    9. .Height = pHeight
    10. .Width = pWidth
    11. End With
    12. 'AddHandler CmdButton.Click, AddressOf CmdButton_Click
    13. Return CmdButton
    14. End Function


    FormLoad:

    VB.NET-Quellcode

    1. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    2. Dim contr As New Control
    3. contr = Ctrl.SetButton("CmdFunction", "Function", 350, 100, 30, 100)
    4. Me.Controls.Add(contr)
    5. Ctrl.SetButton("CmdSub", "Sub", 350, 180, 30, 100)
    6. Ctrl.SetButton("CmdSubByRef", "Sub (ByRef)", 325, 260, 30, 150)
    7. 'Ctrl.SetTextBox("TxtBox_01", " ", 100, 100, 80, 200)
    8. End Sub

    Duster schrieb:

    doch immer den Typ Control nutze und nicht den allgemeinen Typ Object?


    Bei einer Function sollte der Rückgabe-Typ festgelegt werden. Hast du nicht gemacht. Lege den Typ für die Rückgabe fest, dann sollte es gut sein.

    VB.NET-Quellcode

    1. Public Function SetButton(...deine argumente...) As ApfelmussMitBirnenOderControl
    2. End Function

    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin
    Bevor Du weitermachst, bitte die empfohlenen VS-Einstellungen verwenden. Das schließt Option Strict On ein und das wiederum Funktionen ohne Rückgabewert aus, sobald alle Kompilierhinweise/Warnungskonfigurationen scharf (will heißen auf "Fehler") eingestellt sind. Schau dazu in den Projekteinstellungen in den Tab |Kompilieren|

    Klugscheißeritis @NoIde: Ein Apfel muss gar nichts. Wenn dann Apfelmus :P
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.

    Duster schrieb:

    VB.NET-Quellcode

    1. Form1.Controls.Add(CmdButton)
    Das meinte ich nicht, denn das ist die Sch... mist ranz veraltete VB6-Kompatibilitäts-Instanz, die sich dann nicht so verhjältz, wie Du denkst, dass sie sich verhält: Dialoge: Instanziierung von Forms und Aufruf von Dialogen
    Reich eine Instanz der Form oder deren Controls-Instanz in die Prozedur rein, und weisew der Deine eigenen Controls zu.
    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).
    VB-Fragen über PN / Konversation werden ignoriert!
    Zum Glück hat er das in Post#13 schon rausgefunden und erfolgreich angewandt.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.