Control-Techniken: ActionListe und ControlDesigner hinzufügen und benutzen

    • VB.NET

      Control-Techniken: ActionListe und ControlDesigner hinzufügen und benutzen

      Zur Feier meines 1000. Beitrages dachte ich mir es wird mal wieder Zeit für ein Tutorial,
      und da diese Frage auch des öfteren gestellt wird, habe ich mir die Zeit genommen eine kleine Erklärung dazu zu verfassen.
      Natürlich werden für die erfolgreiche Ausführung diverse Grundkenntnisse benötigt.




      Was benötigen Sie?
      Für dieses Tutorial benötigen Sie keine besonderen Komponenten, lediglich ein Control,
      dass Sie mit einer Actionlist bzw. dem ControlDesigner erweitern wollen.

      Für dieses Tutorial verwende ich folgendes TestControl:
      Spoiler anzeigen

      VB.NET-Quellcode

      1. <Designer(GetType(TestControlDesigner))>
      2. Public Class TestControl
      3. Inherits Control
      4. #Region "Declarations"
      5. ''' <summary>
      6. ''' Wird für die Angabe des Aktuellen Mausstatus benötigt.
      7. ''' </summary>
      8. ''' <remarks></remarks>
      9. Private CurrentState As MouseState = MouseState.None
      10. #End Region
      11. #Region "Enumerations"
      12. ''' <summary>
      13. ''' Enum für die Angabe des aktuellen Mausstatus.
      14. ''' </summary>
      15. ''' <remarks></remarks>
      16. Enum MouseState
      17. None = 0
      18. Over = 1
      19. Down = 2
      20. End Enum
      21. #End Region
      22. #Region "Sub-Area"
      23. Protected Overrides Sub OnMouseEnter(e As System.EventArgs)
      24. CurrentState = MouseState.Over
      25. Invalidate()
      26. MyBase.OnMouseEnter(e)
      27. End Sub
      28. Protected Overrides Sub OnMouseLeave(e As System.EventArgs)
      29. CurrentState = MouseState.None
      30. Invalidate()
      31. MyBase.OnMouseLeave(e)
      32. End Sub
      33. Protected Overrides Sub OnMouseDown(e As System.Windows.Forms.MouseEventArgs)
      34. CurrentState = MouseState.Down
      35. Invalidate()
      36. MyBase.OnMouseDown(e)
      37. End Sub
      38. Protected Overrides Sub OnMouseUp(e As System.Windows.Forms.MouseEventArgs)
      39. CurrentState = MouseState.Over
      40. Invalidate()
      41. MyBase.OnMouseUp(e)
      42. End Sub
      43. Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
      44. Dim G As Graphics = e.Graphics
      45. Select Case CurrentState
      46. Case MouseState.None
      47. G.DrawRectangle(New Pen(Brushes.Green), New Rectangle(0, 0, Width - 1, Height - 1))
      48. Case MouseState.Over
      49. G.DrawRectangle(New Pen(Brushes.Yellow), New Rectangle(0, 0, Width - 1, Height - 1))
      50. Case MouseState.Down
      51. G.DrawRectangle(New Pen(Brushes.Red), New Rectangle(0, 0, Width - 1, Height - 1))
      52. End Select
      53. MyBase.OnPaint(e)
      54. End Sub
      55. #End Region
      56. #Region "Properties"
      57. Private _TestpropertyOne As Integer = 5
      58. ''' <summary>
      59. ''' Einfache Testeigenschaft zur veranschaulichung der Actionlist.
      60. ''' </summary>
      61. <Description("Einfache Testeigenschaft zur veranschaulichung der Actionlist.")>
      62. <Category("Testing")>
      63. <DefaultValue(5)>
      64. Public Property TestpropertyOne As Integer
      65. Get
      66. Return _TestpropertyOne
      67. End Get
      68. Set(value As Integer)
      69. _TestpropertyOne = value
      70. End Set
      71. End Property
      72. Private _TestpropertyTwo As Integer = 10
      73. ''' <summary>
      74. ''' Einfache Testeigenschaft zur veranschaulichung der Actionlist.
      75. ''' </summary>
      76. <Description("Einfache Testeigenschaft zur veranschaulichung der Actionlist.")>
      77. <Category("Testing")>
      78. <DefaultValue(10)>
      79. Public Property TestpropertyTwo As Integer
      80. Get
      81. Return _TestpropertyTwo
      82. End Get
      83. Set(value As Integer)
      84. _TestpropertyTwo = value
      85. End Set
      86. End Property
      87. #End Region
      88. End Class





      Was ist eine Actionlist?
      Als Actionlist bezeichnet man das Menü, dass sich beim Klicken auf das kleine Dreieck in der oberen rechten Ecke öffnet.
      Hier sieht man die Actionlist am Beispiel eines meiner Controls:



      Ebenfalls sieht man auf der Abbildung, dass man das Control nur nach links bzw. rechts vergrößern kann.
      Dies wurde mit Hilfe der Control-Designer-Klasse bewerkstelligt.





      Los geht's!
      Zusätzlich zu unser Control-Klasse erstellen wir uns jetzt eine zusätzliche Designer-Klasse.
      Der Name dieser Klasse ist grundsätzlich egal und kann variieren, jedoch ist es klug diesen mit dem Haupt-Control abzustimmen.
      Meine Klasse trägt den Namen: TestControlDesigner. Um diese Klasse nun zu einer ControlDesigner-Klasse zu machen, vererben wir ihr dies mit:
      Inherits System.Windows.Forms.Design.ControlDesigner.
      Als nächstes definieren wir uns noch eine Liste mit Private lists As DesignerActionListCollection

      Mit dem nächsten Schritt geben wir an, zu welchem Control der Designer gehört:

      VB.NET-Quellcode

      1. 'Gib an zu welchem Control der Designer gehört.
      2. Private ReadOnly Property HostControl() As MetroButton
      3. Get
      4. Return DirectCast(Me.Control, MetroButton)
      5. End Get
      6. End Property


      Nun fügen wir zu dem Designer die besagte Actionlist hinzu.
      Dies geschieht ebenfalls anhand einer simplen Eigenschaft:

      VB.NET-Quellcode

      1. 'Fügt die ActionListe zu dem Designer hinzu. (> Menü)
      2. Public Overrides ReadOnly Property ActionLists() As DesignerActionListCollection
      3. Get
      4. If lists Is Nothing Then
      5. lists = New DesignerActionListCollection()
      6. lists.Add(New MetroButtonActionList(Me.Component))
      7. End If
      8. Return lists
      9. End Get
      10. End Property


      Fürs erste wäre es das, da wir nun schon eine ActionList zu unserem Control hinzugefügt haben.
      Dennoch will ich ebenfalls noch ein paar zusätzliche Eigenschaften und Sub's, hinzufügen die ebenfalls sehr hilfreich sind.




      Zusätzliche Funktionen
      Zum Einen möchte ich nun erläutern, wie man dem Control die Richtungen vorgeben kann, in die es vergrößert bzw. verkleinert werden kann.
      Dazu fügen wir ebenfalls zu der ControlDesigner-Klasse eine neue Eigenschaft hinzu. Die Eigentschaft SelectionRules.

      VB.NET-Quellcode

      1. 'Bestimmt wie das Control vergrößert bzw. verkleinert werden kann.
      2. Public Overrides ReadOnly Property SelectionRules() As System.Windows.Forms.Design.SelectionRules
      3. Get
      4. Dim selRules As SelectionRules = Windows.Forms.Design.SelectionRules.Moveable
      5. selRules = selRules Or Windows.Forms.Design.SelectionRules.AllSizeable
      6. Return selRules
      7. End Get
      8. End Property


      Dies ist ein Beispiel, und setzt die SelectionRules auf AllSizable und somit gibt es keinen Unterschied.
      Folgende Enum-Werte kann man der SelectionRules Variabel zuweisen:


      Um z.B. kein verändern der Größe zu erlauben müssen Sie simpel den Wert der selRules Variabel auf folgendes ändern:
      selRules = selRules Or Windows.Forms.Design.SelectionRules.None

      Eine ebenfalls sehr hilfreiche Funktion des ControlDesigners ist, dass man einfach Eigenschaften entfernen kann.
      Dies wird mit folgendem Code bewerkstelligt:

      VB.NET-Quellcode

      1. 'Entfern Eigenschaft auf dem Control.
      2. Protected Overrides Sub PostFilterProperties(ByVal properties As System.Collections.IDictionary)
      3. properties.Remove("BorderStyle")
      4. properties.Remove("RightToLeft")
      5. properties.Remove("Text")
      6. properties.Remove("ForeColor")
      7. properties.Remove("Font")
      8. MyBase.PostFilterProperties(properties)
      9. End Sub





      Verwendung der ActionList
      Kommen wir nun zu dem Teil in dem ich Ihnen zeigen möchte, wie Sie ihr Control mit einer ActionList erweitern können.
      Dies geschieht ebenfalls über eine Klasse. Wie schon vorhin bei der Designerklasse können Sie diese ebenfalls beliebig benennen, jedoch empfehle ich Ihnen diese ebenfalls wie ich TestControlActionList zu nennen.
      Dieser Klasse vererben wir aus DesignerActionList mit Inherits DesignerActionList.
      Anschließend erstellen wir zwei Privates:

      VB.NET-Quellcode

      1. Private _ctrl As TestControl
      2. Private designerActionSvc As DesignerActionUIService = Nothing


      Der nächste Schritt is der, in dem der ActionList das TestControl zugewiesen wird. Dies geschieht in der Sub New

      VB.NET-Quellcode

      1. Public Sub New(ByVal component As IComponent)
      2. MyBase.New(component)
      3. _ctrl = DirectCast(component, TestControl)
      4. Me.designerActionSvc = CType(GetService(GetType(DesignerActionUIService)), DesignerActionUIService)
      5. End Sub


      Im Großen und Ganzen sind wir nun fast fertig, und Sie können gleich ihre ActionList verwenden. Jedoch müssen wir in der ActionList-Klasse nochmals die Eigenschaften deklarieren und erstellen, die unser HostControl besitzt und die in die ActionList eingebaut werden sollen. Diese wären in meinem Fall TestpropertyOne und TestpropertyTwo.
      Diese erstelle ich einfach genau gleich wie in der Hauptklasse des Controls:

      VB.NET-Quellcode

      1. Public Property TestpropertyOne() As Integer
      2. Get
      3. Return _ctrl.TestpropertyOne
      4. End Get
      5. Set(ByVal value As Integer)
      6. _ctrl.TestpropertyOne = value
      7. End Set
      8. End Property
      9. Public Property TestpropertyTwo() As Integer
      10. Get
      11. Return _ctrl.TestpropertyTwo
      12. End Get
      13. Set(ByVal value As Integer)
      14. _ctrl.TestpropertyTwo = value
      15. End Set
      16. End Property


      Ebenfalls möchte ich Ihnen nun zeigen, wie Sie eine Sub via der ActionList aufrufen können.
      Dazu erstellen wir einfach eine simple Sub. In meinem Fall vertauscht diese die Werte der beiden Eigenschaften mit einander.

      VB.NET-Quellcode

      1. Public Sub SwapValues()
      2. Dim i As Integer = _ctrl.TestpropertyOne
      3. _ctrl.TestpropertyOne = _ctrl.TestpropertyTwo
      4. _ctrl.TestpropertyTwo = i
      5. designerActionSvc.Refresh(_ctrl)
      6. End Sub


      Kommen wir nun zum Abschluss des Ganzen. Wir fügen die zwei Eigenschaften und die einzelne Sub zu der ActionList hinzu.
      Dazu erstellen wir eine Funktion die die GetSortedActionItems Funktion überschreibt:

      VB.NET-Quellcode

      1. Public Overrides Function GetSortedActionItems() As System.ComponentModel.Design.DesignerActionItemCollection
      2. Dim items As New DesignerActionItemCollection
      3. items.Add(New DesignerActionHeaderItem("Eigenschaften"))
      4. items.Add(New DesignerActionPropertyItem("TestpropertyOne", "TestpropertyOne:", "Eigenschaften", "Einfache Testeigenschaft zur veranschaulichung der Actionlist."))
      5. items.Add(New DesignerActionPropertyItem("TestpropertyTwo", "TestpropertyTwo:", "Eigenschaften", "Einfache Testeigenschaft zur veranschaulichung der Actionlist."))
      6. items.Add(New DesignerActionMethodItem(Me, "SwapValues", "Swap Values", "Eigenschaften", "Vertauscht die beiden Werte."))
      7. Return (items)
      8. End Function


      Diese Funktion sollte sich eigentlich von selbst erklären, dennoch möchte ich sie noch etwas erläutern:
      items.Add(New DesignerActionHeaderItem("Eigenschaften")) erstellt eine einfache Überschrift.

      items.Add(New DesignerActionPropertyItem("TestpropertyOne", "TestpropertyOne:", "Eigenschaften", "Einfache Testeigenschaft zur veranschaulichung der Actionlist.")) besteht aus folgenden Objekten

      Heißt, dem Namen der Property, dem Anzeigenamen, der Kategorie und einer einfachen Beschreibung.

      Das Hinzufügen der Sub funktioniert grundsätzlich genau gleich bis auf eine kleine Veränderung:

      Bevor man die Methode angibt, muss man noch die ActionList auswählen zu der die Methode gehört. Und dies ist in unserem Fall logischerweise Me.




      Das war's!
      Und schon wurde Ihr Control um eine ActionList und andere hilfreiche Funktionen erweitert.
      Ich hoffe sehr, dass ich Ihnen damit weiterhelfen konnte.

      Natürlich habe ich zum Schluss noch ein paar Downloads hinzugefügt, die Sie ebenfalls als Lernhilfe bzw. Veranschaulichungsmaterial verwenden können.

      Mit freundlichen Grüßen
      Martin Pfeiffer (Gather)
      Bilder
      • Screen3.PNG

        3,94 kB, 267×128, 881 mal angesehen
      Dateien
      Mfg: Gather
      Private Nachrichten bezüglich VB-Fragen werden Ignoriert!