チュートリアル : Windows フォーム コンポーネントへのスマート タグの追加
スマート タグは、メニューに似たユーザー インターフェイス (UI) 要素で、一般的に使用されるデザイン時のオプションを提供します。.NET Framework で提供されるほとんどの標準のコンポーネントおよびコントロールには、スマート タグおよびデザイナーの動詞の拡張機能が含まれています。このチュートリアルの手順では、スマート タグのサポートをコンポーネントおよびコントロールに追加する方法を説明します。
スマート タグを Window フォーム コンポーネントに追加して、一般的に使用されるデザイン時のオプションを提供できます。スマート タグ パネル内の項目は論理的にカテゴリに分類されており、オプションで、デザイナーの動詞エントリに従って個々の DesignerActionMethodItem インスタンスを複製できます。.NET Framework で提供される標準のコンポーネントおよびコントロールの多くには、スマート タグおよびデザイナーの動詞の拡張機能が含まれています。コンポーネントおよびコントロールの作成者は、通常はプッシュ モデルを使用して、スマート タグのサポートを追加することもできます。
プッシュ モデルを使用してスマート タグを追加するには、コンポーネント プロジェクトに以下を追加する必要があります。
DesignerActionList から派生し、スマート タグ メニュー項目の対象となるメソッドおよびプロパティを定義するクラスの実装。このクラスは、DesignerActionItem インスタンスの配列を返す、オーバーライドされる GetSortedActionItems メソッドも提供します。
コンポーネントに関連付けられているデザイナー クラスは、ActionLists プロパティを実装する必要があります。このプロパティを取得すると、単一のスマート タグ メニューに関連付けられているすべての DesignerActionList インスタンスを含む DesignerActionListCollection が提供されます。このようなコレクションには、一覧が 1 つだけ存在する場合があります。
[!メモ]
スマート タグ パネルはスクロールまたはページングをサポートしていないため、パネルに多数のスマート タグ項目を取り込まないように注意してください。項目の数が多すぎると、スマート タグ パネルが画面の境界を越えて拡張する場合があります。
次の手順に、標準の Windows フォーム Label コントロールから派生した ColorLabel という名前の単純なコントロールの例からコードを使用してスマート タグを追加する方法を示します。このコントロールには、ColorLabelDesigner という名前のデザイナーが関連付けられています。
このトピックのコードを単一のリストとしてコピーするには、「方法 : Windows フォーム コンポーネントにスマート タグを追加する」を参照してください。
必須コンポーネント
このチュートリアルを完了するための要件は次のとおりです。
- .NET Framework がインストールされているコンピューターで Windows フォーム アプリケーション プロジェクトを作成および実行するのに必要なアクセス許可。
DesignerActionList から派生したクラスを実装するには
コンポーネントと同じ名前空間に、DesignerActionList から派生したクラスの宣言を追加します。
[!メモ]
デザイン時アセンブリ System.Design.dll への参照を追加する必要があります。このアセンブリは、.NET Framework 4 Client Profile には含まれていません。System.Design.dll への参照を追加するには、プロジェクトのターゲット フレームワークを .NET Framework 4 に変更する必要があります。
Public Class ColorLabelActionList Inherits System.ComponentModel.Design.DesignerActionList
public class ColorLabelActionList : System.ComponentModel.Design.DesignerActionList
関連付けられているコントロールのインスタンスを受け取るコンストラクターをこのクラスに追加します。このインスタンスへの参照を保持するプライベート フィールドを指定します。また、DesignerActionService への参照をキャッシュするためのプライベート フィールドを指定します。これは一覧の更新に使用されます。
Private colLabel As ColorLabel ... Private designerActionUISvc As DesignerActionUIService = Nothing ... Public Sub New(ByVal component As IComponent) MyBase.New(component) Me.colLabel = component ' Cache a reference to DesignerActionUIService, so the ' DesigneractionList can be refreshed. Me.designerActionUISvc = _ CType(GetService(GetType(DesignerActionUIService)), _ DesignerActionUIService) End Sub
private ColorLabel colLabel; ... private DesignerActionUIService designerActionUISvc = null; ... public ColorLabelActionList( IComponent component ) : base(component) { this.colLabel = component as ColorLabel; // Cache a reference to DesignerActionUIService, so the // DesigneractionList can be refreshed. this.designerActionUISvc = GetService(typeof(DesignerActionUIService)) as DesignerActionUIService; }
スマート タグ項目に関連付けるメソッドおよびプロパティを追加します。メソッドは、対応するスマート タグ エントリが選択されると実行されます。プロパティには、現在の値を表示するために getter セクションが必要です。プロパティの値を対応するスマート タグ エントリから編集できるようにする場合は、GetProperties メソッドを使用する setter セクションをオプションで追加できます。
[!メモ]
デザイン時の環境と同様に、プロパティはいずれかの基本型が .NET Framework によって提供された場合にのみ編集でき、型は指定された TypeConverter によって、またはカスタム UITypeEditor が指定されたときに、基本型に変換できます。
Public Property ForeColor() As Color Get Return colLabel.ForeColor End Get Set(ByVal value As Color) GetPropertyByName("ForeColor").SetValue(colLabel, value) End Set End Property ... 'Boolean properties are automatically displayed with binary ' UI (such as a checkbox). Public Property LockColors() As Boolean Get Return colLabel.ColorLocked End Get Set(ByVal value As Boolean) GetPropertyByName("ColorLocked").SetValue(colLabel, value) ' Refresh the list. Me.designerActionUISvc.Refresh(Me.Component) End Set End Property ... Public Sub InvertColors() Dim currentBackColor As Color = colLabel.BackColor BackColor = Color.FromArgb( _ 255 - currentBackColor.R, _ 255 - currentBackColor.G, _ 255 - currentBackColor.B) Dim currentForeColor As Color = colLabel.ForeColor ForeColor = Color.FromArgb( _ 255 - currentForeColor.R, _ 255 - currentForeColor.G, _ 255 - currentForeColor.B) End Sub
public Color ForeColor { get { return colLabel.ForeColor; } set { GetPropertyByName("ForeColor").SetValue(colLabel, value); } } ... // Boolean properties are automatically displayed with binary // UI (such as a checkbox). public bool LockColors { get { return colLabel.ColorLocked; } set { GetPropertyByName("ColorLocked").SetValue(colLabel, value); // Refresh the list. this.designerActionUISvc.Refresh(this.Component); } } ... public void InvertColors() { Color currentBackColor = colLabel.BackColor; BackColor = Color.FromArgb( 255 - currentBackColor.R, 255 - currentBackColor.G, 255 - currentBackColor.B); Color currentForeColor = colLabel.ForeColor; ForeColor = Color.FromArgb( 255 - currentForeColor.R, 255 - currentForeColor.G, 255 - currentForeColor.B); }
オプションで、オーバーライドされたバージョンの GetSortedActionItems メソッドを実装して、DesignerActionItem インスタンスの配列を返します。この各項目は、前の手順で作成したプロパティまたはメソッドに関連付けられています。これにより、項目の順序を変更したり、カテゴリに分類したり、またはオプションで表示したりできます。一覧には、論理グループ タイトルなどの静的な項目も含まれています。
Public Overrides Function GetSortedActionItems() _ As DesignerActionItemCollection Dim items As New DesignerActionItemCollection() 'Define static section header entries. items.Add(New DesignerActionHeaderItem("Appearance")) items.Add(New DesignerActionHeaderItem("Information")) 'Boolean property for locking color selections. items.Add(New DesignerActionPropertyItem( _ "LockColors", _ "Lock Colors", _ "Appearance", _ "Locks the color properties.")) If Not LockColors Then items.Add( _ New DesignerActionPropertyItem( _ "BackColor", _ "Back Color", _ "Appearance", _ "Selects the background color.")) items.Add( _ New DesignerActionPropertyItem( _ "ForeColor", _ "Fore Color", _ "Appearance", _ "Selects the foreground color.")) 'This next method item is also added to the context menu ' (as a designer verb). items.Add( _ New DesignerActionMethodItem( _ Me, _ "InvertColors", _ "Invert Colors", _ "Appearance", _ "Inverts the fore and background colors.", _ True)) End If items.Add( _ New DesignerActionPropertyItem( _ "Text", _ "Text String", _ "Appearance", _ "Sets the display text.")) 'Create entries for static Information section. Dim location As New StringBuilder("Location: ") location.Append(colLabel.Location) Dim size As New StringBuilder("Size: ") size.Append(colLabel.Size) items.Add( _ New DesignerActionTextItem( _ location.ToString(), _ "Information")) items.Add( _ New DesignerActionTextItem( _ size.ToString(), _ "Information")) Return items End Function
public override DesignerActionItemCollection GetSortedActionItems() { DesignerActionItemCollection items = new DesignerActionItemCollection(); //Define static section header entries. items.Add(new DesignerActionHeaderItem("Appearance")); items.Add(new DesignerActionHeaderItem("Information")); //Boolean property for locking color selections. items.Add(new DesignerActionPropertyItem("LockColors", "Lock Colors", "Appearance", "Locks the color properties.")); if (!LockColors) { items.Add(new DesignerActionPropertyItem("BackColor", "Back Color", "Appearance", "Selects the background color.")); items.Add(new DesignerActionPropertyItem("ForeColor", "Fore Color", "Appearance", "Selects the foreground color.")); //This next method item is also added to the context menu // (as a designer verb). items.Add(new DesignerActionMethodItem(this, "InvertColors", "Invert Colors", "Appearance", "Inverts the fore and background colors.", true)); } items.Add(new DesignerActionPropertyItem("Text", "Text String", "Appearance", "Sets the display text.")); //Create entries for static Information section. StringBuilder location = new StringBuilder("Location: "); location.Append(colLabel.Location); StringBuilder size = new StringBuilder("Size: "); size.Append(colLabel.Size); items.Add(new DesignerActionTextItem(location.ToString(), "Information")); items.Add(new DesignerActionTextItem(size.ToString(), "Information")); return items; }
ActionLists プロパティを実装するために関連付けられたデザイナー クラスを更新するには
コントロールのデザイナー クラスを検索します。存在しない場合は、デザイナー クラスを作成してコントロール クラスに関連付けます。デザイナーの詳細については、「基本デザイナー クラス」を参照してください。
最適化の手法として、DesignerActionListCollection 型のプライベート フィールドを追加します。
Private lists As DesignerActionListCollection
private DesignerActionListCollection actionLists;
オーバーライドされた ActionLists プロパティを追加して、前に作成した ColorLabelActionList クラスの新しいインスタンスを返します。
Public Overrides ReadOnly Property ActionLists() _ As DesignerActionListCollection Get If lists Is Nothing Then lists = New DesignerActionListCollection() lists.Add( _ New ColorLabelActionList(Me.Component)) End If Return lists End Get End Property
public override DesignerActionListCollection ActionLists { get { if (null == actionLists) { actionLists = new DesignerActionListCollection(); actionLists.Add( new ColorLabelActionList(this.Component)); } return actionLists; } }
コメント
コードのいくつかの領域では、詳細な説明が必要です。
DesignerActionList から派生したクラス内のプロパティまたはメソッドから、関連付けられているコントロールの状態を変更する場合、コンポーネントのプロパティに対する直接 setter 呼び出しによって変更しないでください。代わりに、適切に作成された PropertyDescriptor を介して変更する必要があります。この間接的な方法により、スマート タグの元に戻す機能と UI 更新アクションが正しく機能します。
DesignerActionUIService.Refresh を呼び出すと、スマート タグ パネルを動的に更新できます。このプロセスを使用すると、スマート タグ パネルの内容を動的に変更できます。この例では、変化する色に関連するスマート タグが LockColors プロパティの状態に応じて含まれます。この Boolean プロパティはスマート タグにも関連付けられるので、開発者は少なくともメニューを使用することにより、現在の色の選択をロックまたはロック解除できます。
DesignerActionMethodItem 型のスマート タグ エントリは、関連付けられているコントロールのショートカット メニューにオプションで含めることができます。それには、コンストラクターの includeAsDesignerVerb パラメーターを true に設定します。これにより、.NET Framework は対応する DesignerVerb を暗黙に作成してショートカット メニューに追加します。この例では、InvertColors 項目がこの方法で処理されます。
スマート タグ項目は、その Category プロパティによってパネル内でグループ化されています。このプロパティは、項目ごとにコンストラクターで設定されています。このプロパティが明示的に設定されていない場合は、既定のカテゴリに割り当てられます。各項目はスマート タグ パネル内にカテゴリ順に並べられます。次に、DesignerActionList クラスから派生したクラスによって返された DesignerActionItem 配列内での出現順に並べられます。この例には、Appearance と Information という 2 つのカテゴリがあります。
[!メモ]
2 つ目のカテゴリには、DesignerActionHeaderItem が指定されません。
静的なテキスト情報を表示するエントリは、DesignerActionTextItem または DesignerActionPropertyItem を使用して実装できます。これらに関連付けられているプロパティには、setter のみが含まれます。この例では、前者の方法を使用します。
次の手順
デザイン時環境へのコンポーネントの統合を開始したら、そのデザイナー サポートを拡張することを検討してください。
デザイン時環境と通信を行うために、属性をメンバーに追加します。詳細については、「Windows フォーム コントロールの属性」を参照してください。
独自のカスタム デザイナーを記述します。詳細については、「方法 : デザイン時機能を活用した Windows フォーム コントロールを作成する」を参照してください。