かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

CollectionEditorのなぞ

前のコレクションエディタ - かずきのBlog@Hatenaの最後の方で作ってたコレクションエディタに下記のようなことをこそっと書いてた。

    internal class GreetCollectionEditor : CollectionEditor
    {
        private Type[] supportTypes = new Type[] { typeof(NormalGreet), typeof(PersonGreet) };

        public GreetCollectionEditor(Type type) : base(type)
        {
            
        }

        protected override Type[] CreateNewItemTypes()
        {
            return supportTypes;
        }

        protected override Type CreateCollectionItemType()
        {
            // ちょっと苦し紛れ…
            return typeof(PersonGreet);
        }
    }

この、ちょっと苦し紛れ…っていう行がないとコレクションエディタでアイテムを追加しても、コレクションの要素のプロパティがうまいこと表示されない。
この苦し紛れの実装は、明らかに苦しすぎるので調べてみた。


とりあえずCollectionEditorのCreateCollectionItemTypeでtypeof(IComponent)を返しておけば問題なさそう…。
格好悪いけど…
何故?

    internal class GreetCollectionEditor : CollectionEditor
    {
        private Type[] supportTypes = new Type[] { typeof(NormalGreet), typeof(PersonGreet) };

        public GreetCollectionEditor(Type type) : base(type)
        {
            
        }

        protected override Type[] CreateNewItemTypes()
        {
            return supportTypes;
        }

        protected override Type CreateCollectionItemType()
        {
            // 多少よくなった?が苦し紛れ
            return typeof(IComponent);
        }
    }


もうちょっと試してみると、Componentを継承してれば問題なくいくということもわかった。
たとえば

public abstract class GreetBase : Component, IGreet
{
  public abstract string GetGreetMessage();
}

public class NormalGreet : GreetBase
{
  ...
}

public class PersonGreet : NormalGreet
{
  ...
}

// GreetBaseのコレクションにする
public class GreetCollection : Collection<GreetBase> { }

これだと、CollectionEditorのCreateCollectionItemTypeメソッドで小細工いれなくてすむ。
CollectionEditorそのものがComponentを扱うことを意識して作られてるからだろうか?
なぞい。


結論としては、とりあえずカスタムコントロール作るときに使うクラスはとりあえずComponent継承して作っておけば問題にぶちあたる可能性も低いだろう。
ということかな?