スポンサーリンク

2010年11月15日月曜日

PropertyGrid で独自クラスのコレクションを編集する方法~その2

 前回のお話の続き。

 今回はいよいよCollectionConverterクラスを継承したコンバータを作成したいと思います。

 具体的には、aspx内部の記述(string)からPropSetCollectionインスタンスへの変換を行うCanConvertFromとConvertFromの実装、その逆のPropSetCollectionインスタンスからaspx内部の記述(string)への変換を行うCanConvertToとConvertToの実装です。

2010年11月11日木曜日

PropertyGrid で独自クラスのコレクションを編集する方法

 今回は珍しく、C#でもASP.NETでのお話。

 Visual Studioでお世話になるPropertyGrid。コントロールを選択するとプロパティウィンドウに表示されるアレ。色とかサイズとかを画面で変更するのにコードを書くことなく設定してくれるアレ。

 独自クラスをプロパティに持つ場合もその設定をPropertyDialogで行うことが可能で、サンプルもちょっとグーグル先生に聞けばちゃら~んと出てくる。が、しかし……これのコレクションを持つパターンが見つからない。

 とりあえずMSDNを見ながら試行錯誤してみたけど、設定値が反映されてなかったり、デザイナー上でエラーが表示されたり(実行時に設定値は反映されエラーも表示されない)……。

 結局どうにもならなくてMSDNのフォーラムに質問投稿。無事に解決?できました。

 結果から言えば、解決になってないような気がする(汗。

2010年6月26日土曜日

CollectionBase とジェネリック

 オブジェクト指向プログラミングをしていると、厳密に型指定された配列やリストを扱いたい場合がある。単純なインスタンスとして使いたいのであればList<T>のようなジェネリックでも問題ないと思うんだけど、昔リストを内包するクラスのソースを見ていて、そのリストがCollectionBaseクラスを継承して書かれていることに気付いた。

 早速MSDNライブラリで検索してみる。


CollectionBase クラス (System.Collections)

厳密に型指定されたコレクションの abstract 基本クラスを提供します。


 うん、あっそう、って感じ。

 ただ、CollectionBaseクラスは基本的にObjectクラスを扱うようになっているので、扱いたい型を使っていくつかのメソッドをオーバーライドしなきゃならない。もちろん、必要なメソッドだけオーバーライドするのもいいけど、オーバーライドしないメソッドはやはり対象はObjectクラスのまま。気持ち悪い。とは言え、全部のメソッドをオーバーライドするのもかったるい。めんどい。

 この手間を省くのにジェネリッククラスを継承してコレクションを作るやり方がある感じ。でも、そうするとどのジェネリッククラスを継承するのかという別の問題も出てくる。Collection<T>とかList<T>とか。それこそ継承するんじゃなくて、List<T>クラスをコンポジションして、必要なインタフェースだけ提供するというのもあり。これだとインタフェースまで限定できる。まあ、これは設計次第。

 話を戻して。じゃあ、どのジェネリッククラスを継承したらいいのか。いろいろとグーグル先生に聞いていたら気になる記事を発見。


LINQifying - getting rid of CollectionBase? - Rick Strahl’s Web Log


 これによると、ただ厳密に型指定されたコレクションを作りたいのであれば、List<T>を継承したクラスを作れば良さそう。ただList<T>クラスにはオーバーライド可能なメソッドがないので、独自の拡張を実装できない。なるほど。

 このようなコレクションを独自に作るということは、厳密に指定する型が独自クラスの場合が多い。そうなると当然、ソートなどの比較方法が単純な大小で行えるものではないので、ソート部分も独自に実装しなくちゃならない。こうなるとList<T>クラスの継承では無理。そこで次に考えるのがCollection<T>クラスの継承を継承すること。ソート処理以外の部分はCollection<T>が肩代わりしてくれてるので、ソート処理だけを追加すればいい。

 さらにさらに、普通のコレクションとしての機能も拡張する必要が出てきた場合。この場合にCollectionBaseクラスを継承する。ただ、これだけだと反復処理に対応しないので、必要ならばIEnumerable<T>インタフェースも実装するよろし。

 ここまでで大体どの状況でどのクラスを継承するべきかが見えてきた。ポイントは拡張の必要性かな?

 拡張の柔軟性の順に選ぶとしたら以下のような感じで。

CollectionBase ⇒ CollectionBase + IEnumerable<T> ⇒ Collection<T> ⇒ List<T>

 今まで気分で使い分けてただけに調べて良かった、すっきりした。

 もし間違って解釈していたら指摘頂ければと思います。