かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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継承して作っておけば問題にぶちあたる可能性も低いだろう。
ということかな?