ネストしたプロパティを展開する

カスタムコントロール作成入門講座中級編

前回の続きです。Shadowプロパティ、無事に読み書きできるようになりましたが、このままでは不便です。Fontプロパティのように、+を押すと展開できるようにしたいですよね。

実は、展開するのはすごく簡単です。TypeConverterを継承するのではなく、そのサブクラスであるExpandableObjectConverterを継承するように変えるだけです。

プロパティウィンドウでShadowの項目を展開して、値を変えてみてください。ColorとDirectionの値を変えると、Shadowの文字列が変わりますよね。ところがDepthの値を変えてもShadowの文字列は変わりません。Depthの値が変わったことをShadowに伝える必要があるからです。それにはNotifyParent属性を使用するか、この後に説明するCreateInstanceメソッドのどちらかを使用します。

また、DefaultValueを設定しているので、展開されたそれぞれの項目のリセットもできます。※なぜColorとDirection(enum型)にはなにも指定しなくてもShadowが変わるのかは、まだ判明していません。

しかし、まだ問題があります。展開された項目を変更しても、フォームに貼り付けたコントロールは再描画されません。再描画するためにはInvalidateを呼ばなければなりませんが、今まで書いたコードでInvalidateをしているのは、Shadowオブジェクトが新しいものに変わった時だけです。現在のShadowオブジェクトの個々の項目の値が変わっただけでは呼ばれないのです。

そこで、個々の値が変わった時に、Shadowオブジェクトを強制的に作り直す、という方法を取ることにします。そのためには、ShadowConverterに次のコードを追加します。

GetCreateInstanceSupportedがtrueを返す時(デフォルトはfalse)、いずれかの項目の値が変更されると、CreateInstanceが呼び出されます。CreateInstanceでは、新しいShadowオブジェクトを作り、渡された現在の値(Dictionary形式)で埋め、これをreturnします。

なお、この方法を取ると、個々の値のリセットができなくなります。しかし、Fontなど既存の展開可能なプロパティもこの方法を取っているので、それらの仕様に合わせるという意味でもこれでよいと思います。

順序が逆になりましたが、最後にShouldSerializeShadowとResetShadowを用意します。

ところで、Shadowクラスの場合はたまたま項目の定義順とソート順が一致していたために気になりませんでしたが、例えばSizeならHeight,Widthの順ではなく、Width,Heightの順にしたいはずです。最後にこの、好きな順にソートする方法を紹介します。ShadowConverterに次のコードを追加します。

なお、このようにGetPropertiesを実装する場合は、ExpandableObjectConverterから継承する必要はなく、TypeConverterから継承することができます。

« »

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

« »