はじめに
カスタムコントロールをControlを継承して作成しました。
デザイナーに対応させようとしたのですが、Controlのプロパティやイベントがプロパティウィンドウにたくさん表示されます。
このコントロールには殆どの項目は不要なので表示したくありません。
やったこと
以下のページを参考に、プロパティを表示しないようにするのは成功しました。
- ControlDesignerクラスを継承したMyControlDesignerクラスを作成する
- PreFilterPropertiesメソッドをオーバーライドする
- 基底クラスControlDesignerのPreFilterProperiesを呼ぶ
- 引数のIDictionaryからプロパティ名をキーとしてPropertyDescriptorを取得する
- 2のPropertyDescriptorから、属性Browsable(false)を追加した新しいPropertyDescriptorを作成する
- 作成したPropertyDescriptorを、プロパティ名をキーとして引数のIDictionaryに設定する
- カスタムコントロールの属性としてMyControlDesignerクラスを指定する
これをイベントについても行おうとして以下のコードを作成しました。
アクションカテゴリの、ClickからMouseDoubleClickまでを非表示にしようとしています。
protected override void PreFilterEvents(IDictionary events)
{
// PreFilterEventsをオーバーライドする場合は必須
base.PreFilterEvents(events);
// 隠したいイベントの名前を追加する
string[] eventsToHide = {
"Click", "DoubleClick", "MouseCaptureChanged", "MouseClick", "MouseDoubleClick",
};
foreach (string eventname in eventsToHide)
{
var ev = (EventDescriptor)events[eventname];
if (ev != null)
{
AttributeCollection runtimeAttributes = ev.Attributes;
// 元の属性数より1個多く確保して、そこに元のをコピー(後ろが1個空く)
Attribute[] attrs = new Attribute[runtimeAttributes.Count + 1];
runtimeAttributes.CopyTo(attrs, 0);
// 一番後ろに属性追加
attrs[runtimeAttributes.Count] = new BrowsableAttribute(false);
// 新しいイベント記述子を作成して、元のイベントを置き換える
ev = TypeDescriptor.CreateEvent(this.GetType(), eventname, ev.EventType, attrs);
events[eventname] = ev;
}
}
}
上手く動かない!
プロパティ表示に切り替えてイベント表示に戻そうとするとVisual Studioが落ちます。
これは困った……。
解決
よくよく見ていて、ひっかかることが。
CreateEventの第一引数のthis.GetType()。this!?
ev = TypeDescriptor.CreateEvent(this.GetType(), eventname, ev.EventType, attrs);
Microsoft Docsによると、ここはコンポーネントの型を指定するそうです。
thisってMyControlDesignerのインスタンスだよね。
EventPropertyのComponentTypeじゃないの?
- ev = TypeDescriptor.CreateEvent(this.GetType(), eventname, ev.EventType, attrs);
+ ev = TypeDescriptor.CreateEvent(ev.ComponentType, eventname, ev.EventType, attrs);
おお、上手くいきました!
ClickからMouseDoubleClickまで非表示になっています。
終わりに
調べてもあまり情報が出てこなかったので書いてみました。
読みづらかったらすみません。
改善点やツッコミ処等があればご指摘お願いします。