Code zu Designtime ausführen

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

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

    Code zu Designtime ausführen

    Hi,

    ich möchte gerne 2 Controls zur Designtime miteinander koppeln.
    Im Prinzip 2 TabControls die zur Designtime immer synchron die Tabs wechseln.

    Im Programm ist das easy:

    VB.NET-Quellcode

    1. Private Sub TabControl1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles TabControl1.SelectedIndexChanged
    2. TabControl2.SelectedIndex = TabControl1.SelectedIndex
    3. End Sub


    Gibt es eine Möglichkeit das auch im Designer hin zu bekommen?

    Bye,

    Dilly
    Wahrscheinlich nur, wenn Du die 2 TabControls in einem UserControl zusammenfasst. Aber unabhängige Controls: nein - AFAIK.
    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.
    @Dilbert Das geht so nicht, da während der Designtime keine Events geworfen werden.
    Da wird ausschließlich InitializeCopmponents() ausgeführt.
    Von einem eingebetteten UserControl wird der Konstruktor ausgeführt, aber ebenfalls keine Events.
    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!
    Hi,
    das mit den Events stimmt wohl nicht so ganz.
    Ich habe das gefunden:
    codeproject.com/Questions/2250…ing-Events-at-Design-Time
    Man kann die Events also irgendwie aktivieren:

    C#-Quellcode

    1. public class MyCustomControl : Control {
    2. public event System.EventHandler TextBoxClick {
    3. add { myTextBox.Click += value; }
    4. remove { myTextBox.Click -= value; }
    5. }
    6. //using generic EventHandler with derived EventArgs is a bit more complex:
    7. public event System.EventHandler<KeyPressEventArgs> TextBoxKeyPress {
    8. add { myTextBox.KeyPress += new KeyPressEventHandler(value); }
    9. remove { myTextBox.KeyPress -= new KeyPressEventHandler(value); }
    10. }
    11. //...
    12. TextBox myTextBox = new TextBox();
    13. } //MyCustomControl


    So wie ich das sehe, muss ich das entsprechende Objekt ableiten und die Events irgendwie "Umbiegen"?
    Leider bin ich aus dem C# Code nicht wirklich schlau geworden.
    Event löschen und gleich wieder zufügen?!?
    Und das innerhalb des Events???
    Ich konnte das in VB jedenfalls nicht nachvollziehen.

    Hat jemand so ein Beispiel in VB auf Lager?

    Bye,

    Dilly
    P.S.: Ich bin nicht sicher, aber ich bilde mir ein, dass das Paint-Event zum Beispiel auch zur DesignTime ausgelöst wird.
    Habe das glaube ich vor vielen Jahren mal mit 'ner Owner-Drawn Listbox gemacht.

    Dilbert schrieb:

    P.S.: Ich bin nicht sicher, aber ich bilde mir ein, dass das Paint-Event zum Beispiel auch zur DesignTime ausgelöst wird.
    Ja, Events werden schon zur DesignZeit ausgelöst.
    Aber sie müssen ja auch empfangen werden.
    Dazu muss man Code schreiben - oder du muss einen Spezial-Designer erst noch erschaffen, mit dem du im Designer festlegen kannst, mit welchem anderen TC das TC gekoppelt sein soll.
    Ja, erb doch einfach mal von TabControl, und gib deinem WunderTC die Property CoupledTabControl As WunderTC.
    Zieh davon zwei aufs Form und verknüpfe sie im Designer - das müsste gehen.

    Wenn du im Designer einem WunderTC das andere zuweist, genau dann(!) wird der Property-Setter aufgerufen.
    Und da kannste dann deine wunderliche Index-Verkopplung implementieren.
    Dann sollte das im Designer worken.

    Beispiel müsste ich basteln - aber ich bastel grad was anderes.
    Vor allem ist solch lausig zu debuggen, weil das eben zur Designzeit abläuft, wo man keine Haltepunkte setzen kann.
    Also wenn ich zwei TCs verkoppeln wollen würde, würde ich im Form_Load eine diesbezügliche Zeile einflechten.

    Das Design-Verhalten von Controls fasse ich nur an, wenn ichs auch wirklich sehr häufig brauche, in vielen Projekten.
    Ja, geht:

    VB.NET-Quellcode

    1. Imports System.Windows.Forms
    2. <System.ComponentModel.DesignerCategory("Code")>
    3. Public Class WunderTC : Inherits TabControl
    4. Public Property CoupledTC() As WunderTC
    5. Get
    6. Return _CoupledTC
    7. End Get
    8. Set
    9. If _CoupledTC Is Value Then Return
    10. _CoupledTC = Value
    11. _CoupledTC.CoupledTC = Me
    12. End Set
    13. End Property
    14. Private WithEvents _CoupledTC As WunderTC
    15. Private Sub _CoupledTC_SelectedIndexChanged(sender As Object, e As EventArgs) Handles _CoupledTC.SelectedIndexChanged
    16. If Me.SelectedIndex = _CoupledTC.SelectedIndex Then Return
    17. Me.SelectedIndex = _CoupledTC.SelectedIndex
    18. End Sub
    19. End Class
    Hi,

    wow, klingt gut!
    Ich werd's mit Tabcontrols testen.
    Dann muss ich schauen wie ich das auf DevExpress RibbonControls und XtraTabControls portiere, da soll das ganze dann zur Anwendung kommen. Und DevExpress ist nochmal 'ne eigene Welt...
    Ich bin aber optimistisch und werde berichten!
    Das mit dem Property hatte ich sowieso genau so vor.

    Kann man da 'ne "Weiche" einbauen?
    Zur Runtime soll noch mehr passieren als zur Designtime?
    Sowas wie "TabControl.IsInDesigner"?

    Bye,

    Dilbert
    Und noch ein P.S.:
    OT: Warum klappt auf dieser Seite kein Copy/Paste und kein DragDrop von Text?
    Liegt das an meinem Browser (FF)?
    Ja liegt am Browser. Man hofft das es mit dem nächsten Update behoben wird. Ich glaube als Abhilfe funktioniert CTRL-Shift-C und CTRL-Shift-V.
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.
    Hi,

    JAAA!
    Funktioniert...
    Ich brauche das nur in 1 Richtung, daher können ein paar Zeilen entfallen.
    Allerdings gibt es ein paar Besonderheiten, ich muß aus verschiedenen Gründen auf "isNothing" prüfen, und es gibt hier einen Sonderfall bei unseren Ribbons, daher darf das nur bei Ribbon-Namen mit mehr als 3 Buchstaben klappen (erklär ich jetzt nicht!).
    Und als letztes sind die Ribbons und Tabs nicht in der gleichen Reihenfolge, haben aber statt dessen die gleiche Namenskonvention, beginnen nur mit einem anderen Buchstaben. Daher die Schleife mit dem Substring.
    Ach ja, auch die Weiche ist drin. Dass ich das gestern Abend nicht gefunden hab' ...
    (Ich lasse in der Klasse nur prüfen, ob das im Designer läuft, der Rest passiert weiterhin im restlichen Code, das machts echt bequem.)
    Also einige Spezialfälle abgefangen. Ansonsten für alle die es interessiert hier der (für mich) komplette Code:

    VB.NET-Quellcode

    1. <System.ComponentModel.DesignerCategory("Code")> Public Class H2TabControlMitRibbonAnbindung
    2. Inherits DevExpress.XtraTab.XtraTabControl
    3. Private WithEvents _AngebundenesRibbonControl As DevExpress.XtraBars.Ribbon.RibbonControl
    4. Public Property AngebundenesRibbonControl As DevExpress.XtraBars.Ribbon.RibbonControl
    5. Get
    6. Return _AngebundenesRibbonControl
    7. End Get
    8. Set(Value As DevExpress.XtraBars.Ribbon.RibbonControl)
    9. _AngebundenesRibbonControl = Value
    10. End Set
    11. End Property
    12. Private Sub _AngebundenesRibbonControl_SelectedPageChanged(sender As Object, e As EventArgs) Handles _AngebundenesRibbonControl.SelectedPageChanged
    13. If Me.DesignMode = True Then
    14. If Not _AngebundenesRibbonControl.SelectedPage Is Nothing Then
    15. If _AngebundenesRibbonControl.SelectedPage.Name.Length > 3 Then
    16. For Each TP As DevExpress.XtraTab.XtraTabPage In Me.TabPages
    17. If TP.Name.Substring(1) = _AngebundenesRibbonControl.SelectedPage.Name.Substring(1) Then Me.SelectedTabPage = TP
    18. Next
    19. End If
    20. End If
    21. End If
    22. End Sub
    23. End Class


    DANKE!

    Bye,

    Dillbert
    Vereinfachung, Verleserlicherung, Verschnellerung (jeweils nur ein bischen):

    VB.NET-Quellcode

    1. Private Sub _AngebundenesRibbonControl_SelectedPageChanged(sender As Object, e As EventArgs) Handles _AngebundenesRibbonControl.SelectedPageChanged
    2. If Not Me.DesignMode Then Return
    3. If _AngebundenesRibbonControl.SelectedPage Is Nothing Then Return
    4. Dim pageName = _AngebundenesRibbonControl.SelectedPage.Name
    5. If pageName.Length < 4 Then Return
    6. For Each TP As DevExpress.XtraTab.XtraTabPage In Me.TabPages
    7. If TP.Name.Substring(1) = pageName.Substring(1) Then Me.SelectedTabPage = TP : Return
    8. Next
    9. End Sub

    Hi,

    Naja, Geschmackssache.
    Ich mag die Einrückung durch die verschachtelten IFs lieber. Da sehe ich dem Code eher an wann was gemacht wird.
    Ich habe mich da sehr dran gewöhnt und mag es nicht mehr missen. Bin auch kein Fan von "RETURN".
    (Wäre RETURN schneller? Ich denke fast nicht. Aber jetzt wirds langsam esoterisch...)
    OK, in der Schleife macht das Sinn um unnötige Durchläufe zu vermeiden, aber ob er 3 Tabs mehr prüft reißt es an Performance nicht raus.
    Und selbst dann kein RETURN, sondern ein EXIT FOR, das finde ich gezielter...
    (Ja, OK, das habe ich jetzt ergänzt...)
    Den Namen in eine Variable zwischenzuspeichern macht das nicht schneller, aber kürzer. Dafür brauche ich dann jedoch eine zusätzliche Zeile.
    Für 2malige Verwendung des Namens ein bisschen übertrieben...
    OK, ich geb's zu, das hab' ich jetzt auch so ;)

    Also alles zusammen:
    Pure Geschmachsache.
    Aber das soll jeder machen wie er mag 8o

    Bevor es zu OT wird:
    Bye,

    Dilbert
    Wie du meinst.
    Aber behalte es im Hinterkopf, dass man durch Returns Verschachtelungen auflösen kann.
    Meiner Erfahrung nacch wird komplexe Code-Verschachtelung schnell zum Problem bezüglich Leserlichkeit, und in Folge Sicherheit.
    Bei sonem einfachen Ding mit 10 Zeilen, wo nur einmal hinein-verschachtelt wird ists natürlicch kein Problem.
    Aber oft bekommt genug man ja seitenweise Zickzack-Linien zu gesicht.
    Hi,

    grundsätzlich bin ich deiner Meinung, aber schau mal folgendes Beispiel an:

    VB.NET-Quellcode

    1. For x As Int32 = 1 To 10
    2. ListBox1.Items.Add(x)
    3. If x = 5 Then Return
    4. Next
    5. ListBox1.Items.Add("666")


    Jaja, ist ja nur ein Beispiel.
    Aber wenn du aus Performancegründen die Schleife vorab verlassen willst ist RETURN recht doof, weil der Eintrag "666" verloren geht.
    Zum vorzeitigen Abbruch von Schleifen verwende ich daher GRUNDSÄTZLICH "Exit For" oder "Exit Do".
    Auch wenn das bei meiner TabControlKlasse von oben egal wäre, da hinter der Schleife nix mehr passiert.
    Umgekehrt verwende ich dann für Prozeduren auch ein EXIT SUB um Verwechslungen zu vermeiden.

    Bye,

    Volker
    P.S.:
    Warum rückt er das so doof ein?!?
    Dann sollte ggf. ein besseres Beispiel gefunden werden, bei dem der Übersichtseffekt der If-Umkehrung besser zu sehen ist, ohne dass unerwünschte Nebeneffekte eintreten - was ja Programmierfehler wären.
    Meine Prozeduren (jou, Geschmackssache, ich weiß) sind fast alle nach einem Schema aufgebaut, bei dem, wenn es Bedingungen gibt, die dafür sorgen, dass der restliche Code nicht abgearbeitet werden könnte, es rechtzeitig dem Leser klar wird:
    statt - analog zu Post#9

    VB.NET-Quellcode

    1. Private Sub AddNewCustomer(CustomerName As String)
    2. If Not String.IsNullOrEmpty(CustomerName) Then
    3. If Not Customers.Any(Function(x) x.Name = CustomerName) Then
    4. Customers.Add(New Customer With {.Name = CustomerName})
    5. End If
    6. End If
    7. End Sub

    heißt es dann bei mir

    VB.NET-Quellcode

    1. Private Sub AddNewCustomer(CustomerName As String)
    2. If Not NameForNewCustomerIsValidAndNew(CustomerName) Then Return
    3. Customers.Add(New Customer With {.Name = CustomerName})
    4. End Sub
    5. Private Function NameForNewCustomerIsValidAndNew(CustomerName As String) As Boolean
    6. If String.IsNullOrEmpty(CustomerName) Then Return False
    7. If Customers.Any(Function(x) x.Name = CustomerName) Then Return False
    8. Return True
    9. End Function
    Ja, eine Kürzung auf eine Zeile à la

    VB.NET-Quellcode

    1. Return Not String.IsNullOrEmpty(CustomerName) AndAlso Not Customers.Any(Function(x) x.Name = CustomerName)
    ist möglich, schadet aber meinem Verständnis der Übersichtlichkeit.

    Zum Thema Einrückung: Wenn man aus VS kopiert und dann Zeilen nachbearbeitet, ist eine manuelle Einrückung im Quellcodemodus nötig, da Tabs und Leerzeichen zwischen Forum und VS unterschiedliche Einrückungen ergeben.
    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.