Add DesignerVerb on UserControl's Properties

后端 未结 2 2104
星月不相逢
星月不相逢 2020-12-18 16:22

EDIT: After I found what I was really looking for, I edited my initial question so to describe better what I finaly wanted to do.

I am working on a <

相关标签:
2条回答
  • 2020-12-18 16:57

    You do not necessarily need to create a custom designer to access the various designer services exposed by the WinForm design environment. All you need is an instance of a IServiceProvider Interface. All classes that have System.ComponentModel.Component in their ancestry expose the Site Property. The Site Property is an instance of type ISite that itself inherits from IServiceProvider.

    Most of the design services are defined by the interfaces documented in the System.ComponentModel.Design Namespace. Others like the BehaviorService Class are buried in the documentation and have to be specifically sought out.

    Using a proper designer class has its advantages in that it automatically integrates into the design model and encapsulates that functionality. The technique shown below has the drawback of needing to know the proper time that services are accessible. The first temporal criteria is that the host designer has finished loading. This is achieved by using a combination the host's IsLoaded property and LoadComplete events. The second is knowing when the host is finished adding your component to the design surface. The setting of the Site Property is part of design transaction. When this transaction is completed, the component's designer is accessible. For this, you use the host's TransactionClosed Event.

    With that stated, the entry point is to override the inherited Site Property so that you can gain access to the service provider. This example gains references to the designer host, its selection service, and the controls default designer. The default designer allows you to add a DesignerVerb to its Verb collection.

    Imports System.ComponentModel
    Imports System.ComponentModel.Design
    
    Public Class DemoControl : Inherits Control
        Public Sub New()
            MyBase.New()
            BackColor = Color.Red ' just so we can see it
        End Sub
    
    #Region "Designer Services"
        Private designerHost As Design.IDesignerHost
        Private myDesigner As Design.IDesigner
        Private designerSelectionService As Design.ISelectionService
        Private Shared customDesignerVerb1 As Design.DesignerVerb
    
        Public Overrides Property Site As ISite
            Get
                Return MyBase.Site
            End Get
            Set(value As ISite)
                MyBase.Site = value
                If value Is Nothing Then ' being removed from the design surface
                    DetachDesignerServices()
                Else ' being added to the design surface
                    designerHost = CType(value.GetService(GetType(Design.IDesignerHost)), Design.IDesignerHost)
                    If designerHost IsNot Nothing Then
                        If designerHost.Loading Then
                            ' the designer has not finished loading, 
                            ' postpone all other connections until it has finished loading
                            AddHandler designerHost.LoadComplete, AddressOf DesignerHostLoaded
                        Else
                            ' designerHost loaded, but is in the in the process of creating this instance
                            If designerHost.InTransaction Then
                                AddHandler designerHost.TransactionClosed, AddressOf DesignerTransactionClosed
                            Else
                                AttachDesignerServices()
                            End If
                        End If
                    End If
                End If
            End Set
        End Property
    
        Private Sub DesignerHostLoaded(sender As Object, e As EventArgs)
            RemoveHandler designerHost.LoadComplete, AddressOf DesignerHostLoaded
            AttachDesignerServices()
        End Sub
    
        Private Sub DesignerTransactionClosed(sender As Object, e As DesignerTransactionCloseEventArgs)
            RemoveHandler designerHost.TransactionClosed, AddressOf DesignerTransactionClosed
            AttachDesignerServices()
        End Sub
    
        Private Sub AttachDesignerServices()
            myDesigner = designerHost.GetDesigner(Me)
            If customDesignerVerb1 Is Nothing Then
                customDesignerVerb1 = New Design.DesignerVerb("Verb1", AddressOf DesignerVerb1EventHandler)
            End If
            If myDesigner IsNot Nothing AndAlso
                Not myDesigner.Verbs.Contains(customDesignerVerb1) Then
                myDesigner.Verbs.Add(customDesignerVerb1)
            End If
    
            designerSelectionService = CType(designerHost.GetService(GetType(Design.ISelectionService)), Design.ISelectionService)
            If designerSelectionService IsNot Nothing Then
                AddHandler designerSelectionService.SelectionChanged, AddressOf DesignerSelectionChanged
            End If
        End Sub
    
        Private Sub DetachDesignerServices()
            If designerSelectionService IsNot Nothing Then
                RemoveHandler designerSelectionService.SelectionChanged, AddressOf DesignerSelectionChanged
                designerSelectionService = Nothing
            End If
            If designerHost IsNot Nothing Then
                RemoveHandler designerHost.LoadComplete, AddressOf DesignerHostLoaded
                designerHost = Nothing
            End If
            If myDesigner IsNot Nothing Then
                myDesigner = Nothing
            End If
        End Sub
    
        Private Sub DesignerSelectionChanged(sender As Object, e As EventArgs)
            Static shownCount As Int32
            If designerSelectionService.GetComponentSelected(Me) AndAlso shownCount < 2 Then
                MessageBox.Show("I've been selected." & If(shownCount = 0, "  This will show one more time on selecting.", ""))
                shownCount += 1
            End If
        End Sub
    
        Private Sub DesignerVerb1EventHandler(sender As Object, e As EventArgs)
            MessageBox.Show("Verb1 Cicked")
        End Sub
    
    #End Region ' "Designer Services
    
    End Class
    
    0 讨论(0)
  • 2020-12-18 17:09

    Well, here is a simple example...

    1. If we haven't done already, we should add a reference to System.Design. Goto Reference Manager > Assemblies > Framework and find System.Design. Check it and click OK.

    2. Into our UserControl code, we make sure that we already have Imports System.ComponentModel and Imports System.ComponentModel.Design references.

    3. Over our UserControl class, we add a Designer attribute, to specify our ControlDesigner for this UserControl.

    Imports System.ComponentModel
    Imports System.ComponentModel.Design
    
    <Designer(GetType(MyControlDesigner))>
    Public Class UserControl1
        'Our UserControl code in here...
    End Class
    

    4. Under our UserControl class, we create a new class by the name "MyControlDesigner" which will be our ControlDesigner.

    Public Class MyControlDesigner
    
    End Class
    

    5. Now, for example, lets create a Verb which will Dock and Undock our UserControl in ParentForm.

    Public Class MyControlDesigner
        Inherits System.Windows.Forms.Design.ControlDesigner 'Inherit from ControlDesigner class.
    
        Private MyVerbs As DesignerVerbCollection
    
        Public Sub New()
    
        End Sub
    
        Public Overrides ReadOnly Property Verbs() As DesignerVerbCollection
            Get
                If MyVerbs Is Nothing Then
                    MyVerbs = New DesignerVerbCollection 'A new DesignerVerbCollection to use for our DesignerVerbs.
                    MyVerbs.Add(New DesignerVerb("Dock In ParentForm", New EventHandler(AddressOf OnMyCommandLinkClicked))) 'An Event Handler for Docking our UserControl.
                    MyVerbs.Add(New DesignerVerb("Undock in ParentForm", New EventHandler(AddressOf OnMyCommandLinkClicked))) 'An Event Handler for Undocking our UserControl.
                    MyVerbs(1).Visible = False 'We hide second Verd by default.
                End If
                Return MyVerbs
            End Get
        End Property
    
        Private Sub OnMyCommandLinkClicked(ByVal sender As Object, ByVal args As EventArgs)
            Dim _UserControl As UserControl1 = CType(Me.Control, UserControl1) 'Reference to our UserControl1 Class, so we can access it's Properties and Methods.
            If _UserControl.Dock = DockStyle.None Then 'If UserControl is Undocked then...
                _UserControl.Dock = DockStyle.Fill 'Dock UserControl in ParentForm.
                MyVerbs(0).Visible = False 'Hide "Dock In ParentForm" DesignerVerb.
                MyVerbs(1).Visible = True 'Show "Undock in ParentForm" DesignerVerb.
            Else
                _UserControl.Dock = DockStyle.None 'Undock UserControl.
                MyVerbs(1).Visible = False 'Hide "Undock in ParentForm" DesignerVerb.
                MyVerbs(0).Visible = True 'Show "Dock in ParentForm" DesignerVerb.
            End If
        End Sub
    End Class
    

    6. Then we Build our project and we add our UserControl into our test Form.

    0 讨论(0)
提交回复
热议问题