Grundsatzfragen - Eigenes Control erstellen

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

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von Haudruferzappeltnoch.

    Grundsatzfragen - Eigenes Control erstellen

    Hallo zusammen,

    ich bin immer noch bei meinem neuen Control und habe da mal ein generelles Problem bzw. Fragen dazu.

    1. Wie kann ich in der Sub New mitbekommen, ob es das Steuerelement schon auf der Form (also hier mal ein kleines Testprg.) gibt, oder ob ich es gerade neu über die Toolbox auf die Form einfüge?

    Warum ich frage ist folgender Grund.

    Die Sub New wird ja bei beiden Aktionen (vorhandes und neues Control) durchlaufen. Soweit habe ich das mit der Sub New schon herausbekommen.

    Diese Zeile mit "InitializeComponent()" bewirkt ja nur, das im Hintergrund die beiden Steuerelemente, die mein neues Control darstellen sollen, in die Form eingefügt und mit bestimmten Eigenschaften versehen werden.
    nimmt man die Zeile raus, dann ist auch die Form sofort leer. Soweit auch klar.

    Jetzt habe ich eine "Standardwerte_einstellen-Eigenschaft" mir eingebaut, die das Aussehen umstellen kann (natürlich sollte dies nur in der Entwurfsansicht passieren). Dazu habe ich die gesamten Eigenschaften per jeweiliger SUB
    so eingestellt, wie ich es für die gerade gewählte Standardwerte_einstellen-Eigenschaft vorsehen möchte. Das Umschalten in der Entwurfsansicht funktioniert auch schon soweit.

    Mein bisherigen Versuche sind daran gescheitert, dass mir beim aktualisieren der DLL die bisher eingefügten Controls die Einstellungen überschrieben wurden.

    Da ich in den Grundeinstellungs-SUB's nun natürlich auch diese Eigenschaft auf Ihren gewünschten Wert setze, bekomme ich immer diesen Grundeinstellungswert eingestellt. Soweit so logisch. Also die Zeile deaktiviert.

    Jetzt steht diese Eigenschaft mit keinem Wert da. Da die Auswahlmöglichkeiten über eine ENUM-Auflistung laufen, habe ich hier den Fehler gefunden. Die Auflistung muss mit 0 beginnen anstatt mit 1.

    Bisher habe ich mit HandleStandardwerte_einstellen_Changed(sender As Object, e As EventArgs) Handles Me.Standardwerte_einstellen_Changed gearbeitet. Dann habe ich es mal mit ..._CLick bzw. ..._DoubleClick versucht, aber leider
    ohne Erfolg.

    2. Gibt es irgendwie eine Möglichkeit, dass meine bisherigen Einstellungen in der Entwurfsansicht im Testprg. bestehen bleiben, aber trotzdem alle Eigenschaften richtig und vollständig darstehen?

    Reagiert werden soll also nur, wenn ich tatsächlich aktiv die jeweilige Eigenschaft ändere.

    3. Gibt es vielleicht auch gute einfach erklärte Bücher, die ich mir hier mal ansehen könnte/sollte?

    Vielleicht kann mir ja auch jemand mal genau den internen Ablauf eines solchen Controls erklären. Welche Sub's bzw. Ereignisse wie Paint, Resize o. ä. kann/muss ich hier ansprechen bzw. auswerten?

    Erst einmal vielen Dank, mal sehen was ihr schreibt.

    Vielen Dank schon einmal im Voraus.

    Volker
    Habe leider noch nicht verstanden, was du meinst.
    Du hast ein Control. Meinst du vielleicht das soll z.B. zur Designzeit grün sein und zur Laufzeit rot?
    Da musst du schauen welcher Prozess den Code ausführt, das ist zur Designzeit einer, der für alle Anwendungen gilt, zur Laufzeit hat jede Anwendung ihren eigenen Prozess.
    @Volker Bunge Zu 2:
    Gib dem Control Public Properties, die werden im Designer angezeigt und deren Werte im Design-Code gespeichert.
    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!
    Hallo Haudruferzappeltnoch,

    schönen Dank erst einmal für die schnelle Antwort.

    Könntest Du mir mal (in einfachen Worten) erklären, wie ein solches Control abläuft und welche Sub's wann greifen? Auch noch gut zu wissen ist vielleicht, wie sich das mit den Eigenschaften (Properties) verhält. Hier speziell wie man die aktuellen Werte an welcher Stelle abfragen kann.

    Da ich intern ja mit _Eigenschaftsvariable arbeite und diese im Public Property NamederEigenschaft as Datentyp per GET auslese und per SET verändere, wäre hier vielleicht auch noch der Unterschied zwischen NamederEigenschaft und der Variable _Eigenschaftsvariable interessant (sind die Werte immer gleich?, sollte man zum Abfragen eines Wertes lieber auf die Variable gehen oder auf den Eigenschaftennamen.
    Gleiches gilt dann auch für das Setzten eines neuen Wertes Variablenname oder NamederEigenschaft.

    Mein Control besteht nur aus einer Picturebox und einer Textbox und soll eine neue Checkbox werden. Natürlich soll sich das Aussehen des Controls den aktuellen Eigenschaften/Variablen anpassen. Ich habe aber nur meine neuen eigenen Eigenschaften in gleichlautende _Variablenamen gepackt. Vererbte Eigenschaften die greife ich über den Eigenschaftennamen ab (wie oben schon gefragt, gibt es hier Vor- und Nachteile dies zu tun, oder ist es einfach
    egal?).

    Eine Eigenschaft soll nur dann reagieren, wenn ich tatsächlich den Wert ändere. Daher hatte ich es schon einmal erfolglos mit ..._click bzw. ..._doubleclick bei den Eigenschaften versucht. Changed greift ja dann, wenn sich der Wert ändert, was ja nach einem Click bzw. DoubleClick ja auch passiert.

    Noch eine Frage fällt mir ein: Wenn ich jetzt eine Eigenschaft per Code ändere, dann geht doch die Änderung über die Public Property GET/SET Routine? Wenn das so für jede Änderung so ist, dann wird beim Set einmal der _Variable der Value-Wert zugewiesen und danach erfolgt dann der Aufruf RaiseEvent SUB-Name, in der dann mein Control mit allen Eigenschaften der neuen Situation angepasst wird.Ich möchte gerne vordefinierte Einstellungen auswählen können. Dazu habe ich mir eine kleine ENUM-Liste gebastelt, die dann jeweils eine SUB aufrufen. In diesen SUB's stehen dann alle Einstellungen drin. Das Wechseln in der Entwurfsansicht funktioniert soweit auch schon. Da ja hier nur die Einstellungen geändert werden, wäre es natürlich schön, wenn man das Neuzeichnen über die Public Property GET/SET Routine solange ausschalten kann, dass wie die Einstellungs-SUB die Werte ändert. Erst danach soll die Aktualisierung einmalig durchgeführt werden.

    Wie Du sieht, bin ich mit meinem Control schon recht weit, aber es hängt eigentlich nur (so hoffe ich) an ein paar kleinen falschen Stellen, die dafür sorgen, dass es nicht so läuft, wie ich mir das so vorstelle.

    Wäre also toll, wenn ich mal ein Grundgerüst bekommen könnte, dass ich dann auf meine Wünsche bzw. Control anwenden könnte.


    Hallo RodFromGermany,

    meine neuen Eigenschaften sehen alle so aus
    Spoiler anzeigen

    VB.NET-Quellcode

    1. ' ************************** Bildgroesse **************************
    2. <Category("Alternative Eigenschaften"),
    3. System.Runtime.InteropServices.ComVisible(True),
    4. Browsable(True),
    5. DefaultValue("14, 14")>
    6. Public Property Bildgroesse As Size
    7. Get
    8. Return _Bildgroesse_Eigenschaft
    9. End Get
    10. Set(value As Size)
    11. If value.Width + value.Height <= 0 Then
    12. value = New Size(10, 10)
    13. MsgBox("Neue Größe 10 x 10")
    14. End If
    15. _Bildgroesse_Eigenschaft = value
    16. RaiseEvent Standard_Aktion_ausfuehren(Me, EventArgs.Empty)
    17. End Set
    18. End Property


    Wenn ich da richtig verstanden habe, dann ist das schon erledigt.

    Oder was meinst Du dann genau?

    Gruß

    Volker

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Volker Bunge“ ()

    Eigenschaft zu Klasse
    verhält sich wie
    Farbe zu Malstift

    Eine vollständige "Standard"-Eigenschaft sieht eigentlich so aus

    VB.NET-Quellcode

    1. Private _Farbe as Color
    2. Property Farbe as Color
    3. Get
    4. Return _Farbe
    5. End Get
    6. Set(value as Color)
    7. Farbe = value
    8. End Set
    9. End Property

    Der Propertykasten Farbe besteht nur aus einer Funktion (der Getter) und einer Methode (der Setter). Da ist per se kein Wert mit assoziiert.
    Der eigentliche Wert der Eigenschaft steckt in _Farbe, so eine Klassenvariable nennt sich Feld. Getter und Setter arbeiten dann mit diesem Feld als Stauraum/Nachschlagewerk.

    Dieser Code befindet sich in nun einer Klasse X. Innerhalb der Klasse X nimmst immer _Farbe und nie Farbe.
    Außerhalb der Klasse X nimmst Farbe, denn _Farbe kannst in diesem Fall da gar nicht nehmen. So isses zumindest Usus. Gehen tuts auch anders
    Wenn sich Code von außerhalb von Klasse X nicht für Farbe interessiert, dann kannst die Property ganz weglassen.

    ReadOnly Properties fehlt der Setter
    WriteOnly Properties fehlt der Getter
    Es gibt auch Properties ohne assoziiertes Feld. Bzw. nutzen solche meistens Felder anderer Properties und konvertieren die oder rechnen was zusammen und haben einfach nur kein persönlich für sich erstelltes Feld.

    Wie weit du mit deinem Control bist kann ich nicht sehen, ist ja kein Code da.
    Aber versuch doch mal an nem konkreten Beispiel zu beschreiben was du willst, was wann passieren soll.

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

    Volker Bunge schrieb:

    Wie kann ich in der Sub New mitbekommen, ob es das Steuerelement schon auf der Form […] gibt, oder ob ich es gerade neu über die Toolbox auf die Form einfüge?
    Brauchst Du das wirklich? Falls ja, dann geht das z.B. über eine Shared Variable, die bei im Konstruktor geändert wird. Will heißen:

    VB.NET-Quellcode

    1. Class Foo
    2. Shared Counter As Integer = 0 'geht auch als Boolean(-Flag)
    3. Sub New()
    4. If Counter > 0 Then MessageBox.Show($"Es gibt schon {Counter} Instanzen von mir.")
    5. Counter += 1
    6. End Sub
    7. End Class

    Volker Bunge schrieb:

    "InitializeComponent()" bewirkt ja nur, das im Hintergrund die beiden Steuerelemente, die mein neues Control darstellen sollen, in die Form eingefügt und mit bestimmten Eigenschaften versehen werden.
    Nein, das stimmt so nicht ganz. Es gibt in dieser Situation 2x InitializeComponent. Einmal in der UserControl.Designer.vb, welche dazu führt, dass die im Designer festgelegten, initialen/default UserControl-Eigenschaften gesetzt werden, die Du im Designer sehen kannst, wenn Du Dir die UserControl.vb im Designer ansiehst. Und es gibt die InitializeComponent-Methode des Forms, welche die tatsächlichen/spezifischen Eigenschaften der UserControl-Instanz setzt.

    Haudruferzappeltnoch schrieb:

    Innerhalb der Klasse X nimmst immer _Farbe und nie Farbe.
    Da kann ich nicht zustimmen. Wenn z.B. im Setter sinnvolle Wertprüfungen stattfinden, sollte auch innerhalb der Klasse nicht mit _Farbe, sondern mit Farbe gearbeitet werden.
    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.
    zu 1) glaub das geht garnet.
    Es ist unvorhersehbar, wann der Designer refresht, und also den DesignerCode ausführt.
    Eine Shared-Variable - etwa ein Counter - würde da schön hochzählen.
    Aber dann zurückgesetzt, wenn neu kompiliert wird.

    Btw eine Messagebox in Sub New wäre disfunktional, ist aber zum Einarbeiten ins Thema sehr interessant.
    Die poppt dann nämlich immer auf, wenn der Designer refresht. (Und blockiert damit den Designer)

    VaporiZed schrieb:

    Da kann ich nicht zustimmen. Wenn z.B. im Setter sinnvolle Wertprüfungen stattfinden, sollte auch innerhalb der Klasse nicht mit _Farbe, sondern mit Farbe gearbeitet werden.
    Ayjo, gehen tuts natürlich auch dann. Die Wertprüfung kann man in eine Private Function kapseln, diese kann man dann in der Property aufrufen, und innerhalb der Klasse auch ansonsten anders nutzen.

    Man kann auch immer die Property nutzen, ich denke da wird man wohl eher schwierig einen Unterschied feststellen.