.NET ROOM.NET ROOMトップへCOMRADE総合トップへ
「3:デザイン時に自作コントロールの設定を変更する方法」へ

カスタムエディタ(デザイナ)の表示

 サンプルMyPoint5を元に以下の解説を行います。

 カスタムエディタをVS.NETのデザイン画面から起動するためには、ControlDesignerクラスを使用します。
ただし、名前から連想できるように、ControlDesignerそのもの自体がデザイナの土台というわけではありません。
“デザイナなどのインターフェイスを提供する土台”というようなものだと言えます。

 具体的には、“動詞”という意味の「Verbs」というプロパティを設定することで、
コントロールに特有のいくつかの処理をVS.NETのデザイン画面のコンテキストメニュー(図10)、
もしくはコントロールのプロパティウィンドウ(図11)に提供します。

図10:右クリックで表示されるメニュー。デザイン画面に表示されたVerbs



図11:プロパティウィンドウに表示されたVerbs


 Verbsプロパティは、DesignerVerbのコレクションを返します。
以下のようにDesignerVerbの配列を作成し、DesignerVerbCollectionの新しいインスタンスを初期化しています。

   public override DesignerVerbCollection Verbs {
    get {
     DesignerVerb[] verbs = new DesignerVerb[] {
      new DesignerVerb("Launch MyLabel Designer.(&L)",
       new EventHandler(launch_designer))
     };
     return new DesignerVerbCollection(verbs);
    }
   }

 DesignerVerbのコンストラクタには、コンテキストメニューおよび、プロパティウィンドウに表示される文字列と、
EventHandler型のDelegateを指定します。
文字列に、上記のようにアンパサンド(&)を使用すると、直後の文字が、
図10図11のように下線付きで表示され、キーボードナビゲーション時のアクセスキーの対象になります。[注1

 登録したDelegateは以下のように実装してあります。

   void launch_designer(object sender, EventArgs e) {
    MyPointControl mpc = Control as MyPointControl;
    DesignerForm form = new DesignerForm();
    form.MPC.Point = mpc.Point;
    if (form.ShowDialog() == DialogResult.OK)
     mpc.Point = form.MPC.Point;
   }

  ControlDesigner.Controlプロパティを使用して、いつでもデザイン対象のコントロールに
アクセスすることが可能です。
ControlDesignerはコントロールに対して以下のように、DesignerAttributeを使用して関連付けます。

   [Designer(typeof(MyPointDesigner))]

 なお、ソースコードの詳細はサンプルを参照してください。


---------------------------------------------------------------------------
注1)右クリック、または [Shift] + [F10] でコンテキストメニューを表示した状態で、
[Shift] とここで指定したキーを押すことによって、すばやく選択することが出来ます。



ページトップへ


デザイン時のコードを別アセンブリにする

 ここまで説明してきた、DesignerAttributeおよび、EditorAttributeはコンストラクタで「typeof(...)」のように、
静的に型を指定していましたが、これらのAttributeのコンストラクタには、String型の引数を取るものもあります。
これは、「Reflection」という、動的に型の情報を取得する仕組みが利用されています。[注2

 この仕組みを利用して、デザイン時のコードを別アセンブリにして、
コントロールのアセンブリから呼び出すことができます。
なお、静的リンクを使用してもアセンブリを別にすることが可能ですが、その場合は、
コントロールとデザイン時用のアセンブリが相互に依存するという循環参照の問題が発生してしまいます。

   [Designer("MyControls.Design.MyPointDesigner, Design")]
   public class MyPointControl : Control {
   (略)
   [Editor("MyControls.Design.MyPointUIEditor,
    Design", typeof(UITypeEditor))]
   [TypeConverter(typeof(MyPointConverter))]
   public class MyPoint {
   (略)

 注意すべき点は、静的リンクと違って、文字列で型を指定する場合は、
引数の文字列を間違えていても、コンパイル時にはチェックされないということです。
自分の指定したUITypeEditor及びDesignerが思惑通りに使用されているかどうかをよく確認する必要があるでしょう。

  このように文字列を使用したAttributeの指定は便利なのですが、複雑なため、
「開発途中では、同じアセンブリで作成し、最後にアセンブリを分離する」という方法をお勧めします。

 ここで説明したソースコードの詳細はサンプルReflectionを参照してください。


---------------------------------------------------------------------------
注2)Reflectionに関しては次回のコラムでもう少し詳しく解説する予定です。



ページトップへ


最後に

 今回は、デザイン時にカスタムクラスの設定を変更する方法として「プロパティエディタを使用する方法」および
「カスタムエディタを使用する方法」を解説してきました。
しかし、これらを実際に実行してみると、変更した値が反映されず、初期値が設定されてしまうことに気づくと思います。
また、VS.NETによって自動生成されるソースコードを眺めてみても、変更された値が反映されていません。

 これは、カスタムプロパティが永続化されていないため、起こってしまう現象です。
次回は、カスタムクラスの永続化のために必要な「シリアライズ」を解説してゆきます。


前へ | ページトップへ | 次へ