方法 : コントロール用デザイナーを実装する

ここでは、「方法 : HelpLabel 拡張プロバイダーを実装する」で説明されている HelpLabel 拡張プロバイダー コントロールのデザイナー (HelpLabelDesigner) を実装する方法について説明します。 このデザイナーは、HelpLabel コントロール内の入れ子になったクラスです。 このデザイナーのコード例では、次の点を示します。

  • HelpLabelDesigner は、ControlDesigner から派生します。

  • HelpLabelDesigner は、IDesigner インターフェイスに指定された Verbs プロパティをオーバーライドすることによって、デザイナー動詞を提供します。 デザイン時には、動詞はデザイナーに関連付けられたオブジェクト上のコマンドとして表示されます。 詳細については、「デザイナー動詞」を参照してください。

  • HelpLabelDesigner は、IDesignerFilter インターフェイスによって指定された PreFilterProperties メソッドをオーバーライドすることにより、デザイン時プロパティ (TrackSelection) を HelpLabel に追加します。 プロパティとイベントの追加と置換の詳細については、「メタデータ フィルター処理」を参照してください。

次のコード例には、デザイナーのコードが含まれています。

注意

次のデザイナー コード自体はコンパイルされません。代わりに、入れ子になったクラスとしてデザイナーのコードを含む「方法 : HelpLabel 拡張プロバイダーを実装する」の例がコンパイルされます。

' 
' <doc> 
' <desc> 
'      This is a designer for the HelpLabel.  This designer provides 
'      design time feedback for the label.  The help label responds 
'      to changes in the active control, but these events do not 
'      occur at design time.  In order to provide some usable feedback 
'      that the control is working the right way, this designer listens 
'      to selection change events and uses those events to trigger active 
'      control changes. 
' </desc> 
' </doc> 
'
<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
Public Class HelpLabelDesigner
    Inherits System.Windows.Forms.Design.ControlDesigner

    Private _trackSelection As Boolean = True 

    ' <summary> 
    ' This property is added to the control's set of properties in the method 
    ' PreFilterProperties below.  Note that on designers, properties that are 
    ' explictly declared by TypeDescriptor.CreateProperty can be declared as 
    ' private on the designer.  This helps to keep the designer's public 
    ' object model clean. 
    ' </summary>
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
    Private Property TrackSelection() As Boolean 
        Get 
            Return _trackSelection
        End Get 
        Set(ByVal Value As Boolean)
            _trackSelection = Value
            If _trackSelection Then 
                Dim ss As ISelectionService = CType(GetService(GetType(ISelectionService)), ISelectionService)
                If (ss IsNot Nothing) Then
                    UpdateHelpLabelSelection(ss)
                End If 
            Else 
                Dim helpLabel As HelpLabel = CType(Control, HelpLabel)
                If (helpLabel.activeControl IsNot Nothing) Then
                    helpLabel.activeControl = Nothing
                    helpLabel.Invalidate()
                End If 
            End If 
        End Set 
    End Property 

    Public Overrides ReadOnly Property Verbs() As DesignerVerbCollection
        Get 
            Dim myVerbs() As DesignerVerb = {New DesignerVerb("Sample Verb", AddressOf OnSampleVerb)}
            Return New DesignerVerbCollection(myVerbs)
        End Get 
    End Property 

    ' 
    ' <doc> 
    ' <desc> 
    '      Overrides Dispose.  Here we remove our handler for the selection changed 
    '      event.  With designers, it is critical that they clean up any events they 
    '      have attached.  Otherwise, during the course of an editing session many 
    '      designers might get created and never destroyed. 
    ' </desc> 
    ' </doc> 
    ' 
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then 
            Dim ss As ISelectionService = CType(GetService(GetType(ISelectionService)), ISelectionService)
            If (ss IsNot Nothing) Then 
                RemoveHandler ss.SelectionChanged, AddressOf OnSelectionChanged
            End If 
        End If 
        MyBase.Dispose(disposing)
    End Sub 

    ' 
    ' <doc> 
    ' <desc> 
    '       Overrides initialize.  Here we add an event handler to the selection service. 
    '      Notice that we are very careful not to assume that the selection service is 
    '      available.  It is entirely optional that a service is available and you should 
    '      always degrade gracefully if a service cannot be found. 
    ' </desc> 
    ' </doc> 
    ' 
    Public Overrides Sub Initialize(ByVal component As IComponent)
        MyBase.Initialize(component)

        Dim ss As ISelectionService = CType(GetService(GetType(ISelectionService)), ISelectionService)
        If (ss IsNot Nothing) Then 
            AddHandler ss.SelectionChanged, AddressOf OnSelectionChanged
        End If 
    End Sub 

    Private Sub OnSampleVerb(ByVal sender As Object, ByVal e As EventArgs)
        MessageBox.Show("You have just invoked a sample verb.  Normally, this would do something interesting.")
    End Sub 

    ' 
    ' <doc> 
    ' <desc> 
    '      The handler for the selection change event.  Here we update the active control within 
    '      the help label. 
    ' </desc> 
    ' </doc> 
    ' 
    Private Sub OnSelectionChanged(ByVal sender As Object, ByVal e As EventArgs)
        If _trackSelection Then 
            Dim ss As ISelectionService = CType(sender, ISelectionService)
            UpdateHelpLabelSelection(ss)
        End If 
    End Sub 

    Protected Overrides Sub PreFilterProperties(ByVal properties As IDictionary)
        ' Always call base first in PreFilter* methods, and last in PostFilter* 
        ' methods. 
        MyBase.PreFilterProperties(properties)

        ' We add a design-time property called TrackSelection that is used to track 
        ' the active selection.  If the user sets this to true (the default), then 
        ' we will listen to selection change events and update the control's active 
        ' control to point to the current primary selection.
        properties("TrackSelection") = TypeDescriptor.CreateProperty( _
           Me.GetType(), _
           "TrackSelection", _
           GetType(Boolean), _
           New Attribute() {CategoryAttribute.Design})
    End Sub 

    ' <summary> 
    ' This is a helper method that, given a selection service, will update the active control 
    ' of the help label with the currently active selection. 
    ' </summary> 
    ' <param name="ss"></param> 
    Private Sub UpdateHelpLabelSelection(ByVal ss As ISelectionService)
        Dim c As Control = CType(ss.PrimarySelection, Control)
        Dim helpLabel As HelpLabel = CType(Control, HelpLabel)
        If (c IsNot Nothing) Then
            helpLabel.activeControl = c
            helpLabel.Invalidate()
        Else 
            If (helpLabel.activeControl IsNot Nothing) Then
                helpLabel.activeControl = Nothing
                helpLabel.Invalidate()
            End If 
        End If 
    End Sub 

    Public Sub New()

    End Sub 
End Class
        // 
        // <doc> 
        // <desc> 
        //      This is a designer for the HelpLabel.  This designer provides 
        //      design time feedback for the label.  The help label responds 
        //      to changes in the active control, but these events do not 
        //      occur at design time.  In order to provide some usable feedback 
        //      that the control is working the right way, this designer listens 
        //      to selection change events and uses those events to trigger active 
        //      control changes. 
        // </desc> 
        // </doc> 
        //
        [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] 
        public class HelpLabelDesigner : System.Windows.Forms.Design.ControlDesigner 
        {

            private bool trackSelection = true;

            /// <summary> 
            /// This property is added to the control's set of properties in the method 
            /// PreFilterProperties below.  Note that on designers, properties that are 
            /// explictly declared by TypeDescriptor.CreateProperty can be declared as 
            /// private on the designer.  This helps to keep the designer's publi 
            /// object model clean. 
            /// </summary>
            [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
            private bool TrackSelection
            {
                get
                {
                    return trackSelection;
                }
                set
                {
                    trackSelection = value;
                    if (trackSelection)
                    {
                        ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService));
                        if (ss != null)
                        {
                            UpdateHelpLabelSelection(ss);
                        }
                    }
                    else
                    {
                        HelpLabel helpLabel = (HelpLabel)Control;
                        if (helpLabel.activeControl != null)
                        {
                            helpLabel.activeControl = null;
                            helpLabel.Invalidate();
                        }
                    }
                }
            }

            public override DesignerVerbCollection Verbs
            {
                get
                {
                    DesignerVerb[] verbs = new DesignerVerb[] {
                                                                  new DesignerVerb("Sample Verb", new EventHandler(OnSampleVerb))
                                                              };
                    return new DesignerVerbCollection(verbs);
                }
            }

            // 
            // <doc> 
            // <desc> 
            //      Overrides Dispose.  Here we remove our handler for the selection changed 
            //      event.  With designers, it is critical that they clean up any events they 
            //      have attached.  Otherwise, during the course of an editing session many 
            //      designers may get created and never destroyed. 
            // </desc> 
            // </doc> 
            // 
            protected override void Dispose(bool disposing) 
            {
                if (disposing) 
                {
                    ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService));
                    if (ss != null) 
                    {
                        ss.SelectionChanged -= new EventHandler(OnSelectionChanged);
                    }
                }

                base.Dispose(disposing);
            }

            // 
            // <doc> 
            // <desc> 
            //       Overrides initialize.  Here we add an event handler to the selection service. 
            //      Notice that we are very careful not to assume that the selection service is 
            //      available.  It is entirely optional that a service is available and you should 
            //      always degrade gracefully if a service could not be found. 
            // </desc> 
            // </doc> 
            // 
            public override void Initialize(IComponent component) 
            {
                base.Initialize(component);

                ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService));
                if (ss != null) 
                {
                    ss.SelectionChanged += new EventHandler(OnSelectionChanged);
                }
            }

            private void OnSampleVerb(object sender, EventArgs e)
            {
                MessageBox.Show("You have just invoked a sample verb.  Normally, this would do something interesting.");
            }

            // 
            // <doc> 
            // <desc> 
            //      Our handler for the selection change event.  Here we update the active control within 
            //      the help label. 
            // </desc> 
            // </doc> 
            // 
            private void OnSelectionChanged(object sender, EventArgs e) 
            {
                if (trackSelection)
                {
                    ISelectionService ss = (ISelectionService)sender;
                    UpdateHelpLabelSelection(ss);
                }
            }

            protected override void PreFilterProperties(IDictionary properties)
            {
                // Always call base first in PreFilter* methods, and last in PostFilter* 
                // methods. 
                base.PreFilterProperties(properties);

                // We add a design-time property called "TrackSelection" that is used to track
                // the active selection.  If the user sets this to true (the default), then 
                // we will listen to selection change events and update the control's active 
                // control to point to the current primary selection.
                properties["TrackSelection"] = TypeDescriptor.CreateProperty(
                    this.GetType(),        // the type this property is defined on 
                    "TrackSelection",    // the name of the property 
                    typeof(bool),        // the type of the property 
                    new Attribute[] {CategoryAttribute.Design});    // attributes
            }

            /// <summary> 
            /// This is a helper method that, given a selection service, will update the active control 
            /// of our help label with the currently active selection. 
            /// </summary> 
            /// <param name="ss"></param>
            private void UpdateHelpLabelSelection(ISelectionService ss)
            {
                Control c = ss.PrimarySelection as Control;
                HelpLabel helpLabel = (HelpLabel)Control;
                if (c != null)
                {
                    helpLabel.activeControl = c;
                    helpLabel.Invalidate();
                }
                else
                {
                    if (helpLabel.activeControl != null)
                    {
                        helpLabel.activeControl = null;
                        helpLabel.Invalidate();
                    }
                }
            }
        }

参照

処理手順

方法 : HelpLabel 拡張プロバイダーを実装する

その他の技術情報

カスタム デザイナー

デザイン時サポートの拡張