- PR -

IExtenderProvider での複合Enumプロパティの実装

1
投稿者投稿内容
ハロ
会議室デビュー日: 2007/06/12
投稿数: 6
投稿日時: 2007-12-02 10:06
以前、Enum型の複合プロパティのスレッドで、質問させて頂いた者です。

これの応用の話になるのですが、IExtenderProvider で、
上記の内容(Enum型の複合プロパティ)を実装したいと思っています。

StandardValuesCollection 内で、FieldCategory プロパティの設定値によって
FieldSubCategory プロパティの選択肢を狭め様としているのですが、
FieldCategory プロパティの設定値を得る為に IExtenderListService を使って
TestExtender オブジェクトを見つけています。
ただ、この方法では本当の意味での”特定”では無い為、
例えば TestExtender オブジェクトが複数置かれている場合には
正しく動作しません。

FieldCategory プロパティの値を、もっとすっきりと確実に取得する方法が
あるのでは無いかと思っているのですが、なかなか糸口がつかめずにいます。
何か良い方法がありましたら、ご協力を頂ければと思っています。
宜しくお願い致します。

以下が、サンプルソースです。
(問題の箇所は「ここを改善したい」のコメントのところになります)

コード:

using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;

namespace Sample.Extender
{
/// --------------------------------------------------------------------------------
/// <summary>
/// </summary>
/// --------------------------------------------------------------------------------
public enum FieldCategory
{
None,
CategoryX,
CategoryY,
CategoryZ
}

/// --------------------------------------------------------------------------------
/// <summary>
/// </summary>
/// --------------------------------------------------------------------------------
public enum FieldSubCategory
{
None,
SubCategoryX1,
SubCategoryX2,
SubCategoryX3,
SubCategoryY1,
SubCategoryY2,
SubCategoryY3,
SubCategoryZ1,
SubCategoryZ2,
SubCategoryZ3
}

[ProvideProperty("FieldCategory", typeof(Component)),
ProvideProperty("FieldSubCategory", typeof(Component))]
public class TestExtender : Component, IExtenderProvider
{
private Dictionary<Component, FieldCategory> fieldCategories = new Dictionary<Component, FieldCategory>();
private Dictionary<Component, FieldSubCategory> fieldSubCategories = new Dictionary<Component, FieldSubCategory>();

public class FieldSubCategoryConverter : EnumConverter
{
public FieldSubCategoryConverter(Type type)
: base(type)
{
}

public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
//-------------------- (ここを改善したい) --------------------
TestExtender targetExtender = null;
IExtenderListService extenderListService = (IExtenderListService)context.GetService(typeof(IExtenderListService));
if (extenderListService != null) {
IExtenderProvider[] extenders = extenderListService.GetExtenderProviders();
for (int i = 0; i < extenders.Length; i++) {
if (extenders[i].GetType() == typeof(TestExtender)) {
targetExtender = (TestExtender)extenders[i];
break;
}
}
}
//------------------------------------------------------------

System.Collections.ArrayList range = new System.Collections.ArrayList();
range.Add(FieldSubCategory.None);

if (targetExtender != null) {
Control control = (Control)context.Instance;
FieldCategory fieldCategory = targetExtender.GetFieldCategory(control);
switch (fieldCategory)
{
case FieldCategory.CategoryX:
range.Add(FieldSubCategory.SubCategoryX1);
range.Add(FieldSubCategory.SubCategoryX2);
range.Add(FieldSubCategory.SubCategoryX3);
break;
case FieldCategory.CategoryY:
range.Add(FieldSubCategory.SubCategoryY1);
range.Add(FieldSubCategory.SubCategoryY2);
range.Add(FieldSubCategory.SubCategoryY3);
break;
case FieldCategory.CategoryZ:
range.Add(FieldSubCategory.SubCategoryZ1);
range.Add(FieldSubCategory.SubCategoryZ2);
range.Add(FieldSubCategory.SubCategoryZ3);
break;
}
}

return new StandardValuesCollection(range);
}
}

public TestExtender()
{
}

public TestExtender(IContainer container)
{
container.Add(this);
}

public void SetFieldCategory(Component component, FieldCategory fieldCategory)
{
if (fieldCategories.ContainsKey(component)) {
fieldCategories.Remove(component);
}
fieldCategories.Add(component, fieldCategory);

SetFieldSubCategory(component, FieldSubCategory.None);
}

[DefaultValue(FieldCategory.None),
Category("データ"),
Description("入力項目のカテゴリを示す値を取得または設定します。")]
public FieldCategory GetFieldCategory(Component component)
{
return fieldCategories.ContainsKey(component) ? fieldCategories[component] : FieldCategory.None;
}

public void SetFieldSubCategory(Component component, FieldSubCategory fieldSubCategory)
{
if (fieldSubCategories.ContainsKey(component)) {
fieldSubCategories.Remove(component);
}
fieldSubCategories.Add(component, fieldSubCategory);
}

[DefaultValue(FieldSubCategory.None),
Category("データ"),
Description("入力項目のサブカテゴリを示す値を取得または設定します。"),
TypeConverter(typeof(FieldSubCategoryConverter))]
public FieldSubCategory GetFieldSubCategory(Component component)
{
return fieldSubCategories.ContainsKey(component) ? fieldSubCategories[component] : FieldSubCategory.None;
}

bool IExtenderProvider.CanExtend(object target)
{
if (target is Control && !(target is TestExtender)) {
return true;
}
return false;
}
}
}



# 表現が分かりずらかったので、随所に「プロパティ」の文言を追加

[ メッセージ編集済み 編集者: ハロ 編集日時 2007-12-04 09:34 ]
ハロ
会議室デビュー日: 2007/06/12
投稿数: 6
投稿日時: 2007-12-04 09:31
自己レスです。
解決ではなく代替案なんですが、
拡張プロバイダのプロパティ値を格納している変数(fieldCategories、fieldSubCategories) を static 宣言し、
そうする事で入れ子クラス(FieldSubCategoryConverter) 内からでも参照できる様になるので、
GetStandardValues メソッド内でそれを参照し、FieldSubCategory の選択肢を狭める様にしました。
(下記のコードの通り)

弊害として、TestExtender オブジェクトが複数配置された場合に、
fieldCategories、fieldSubCategories 変数の実体が一つしか存在しない為、
TestExtender の各オブジェクトの拡張プロパティの値が連動してしまいます。
その様な使い方は、そもそも想定してないので、問題無いといえば問題無いんですが・・・・

もっと良い方法(TestExtender オブジェクトが複数配置されたとしても、
それぞれの値を保持できる方法)ってないものでしょうか・・・・

コード:
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;

namespace Sample.Extender
{
    /// --------------------------------------------------------------------------------
    /// <summary>
    ///    </summary>
    /// --------------------------------------------------------------------------------
    public enum FieldCategory
    {
        None,
        CategoryX,
        CategoryY,
        CategoryZ
    }

    /// --------------------------------------------------------------------------------
    /// <summary>
    ///    </summary>
    /// --------------------------------------------------------------------------------
    public enum FieldSubCategory
    {
        None,
        SubCategoryX1,
        SubCategoryX2,
        SubCategoryX3,
        SubCategoryY1,
        SubCategoryY2,
        SubCategoryY3,
        SubCategoryZ1,
        SubCategoryZ2,
        SubCategoryZ3
    }

    [ProvideProperty("FieldCategory", typeof(Component)),
    ProvideProperty("FieldSubCategory", typeof(Component))]
    public class TestExtender : Component, IExtenderProvider
    {
        private static Dictionary<Component, FieldCategory> fieldCategories = new Dictionary<Component, FieldCategory>();
        private static Dictionary<Component, FieldSubCategory> fieldSubCategories = new Dictionary<Component, FieldSubCategory>();

        private class FieldSubCategoryConverter : EnumConverter
        {
            public FieldSubCategoryConverter(Type type)
                : base(type)
            {
            }

            public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
            {
                System.Collections.ArrayList range = new System.Collections.ArrayList();
                range.Add(FieldSubCategory.None);

                Control control = (Control)context.Instance;

                switch (fieldCategories[control])
                {
                    case FieldCategory.CategoryX:
                        range.Add(FieldSubCategory.SubCategoryX1);
                        range.Add(FieldSubCategory.SubCategoryX2);
                        range.Add(FieldSubCategory.SubCategoryX3);
                        break;
                    case FieldCategory.CategoryY:
                        range.Add(FieldSubCategory.SubCategoryY1);
                        range.Add(FieldSubCategory.SubCategoryY2);
                        range.Add(FieldSubCategory.SubCategoryY3);
                        break;
                    case FieldCategory.CategoryZ:
                        range.Add(FieldSubCategory.SubCategoryZ1);
                        range.Add(FieldSubCategory.SubCategoryZ2);
                        range.Add(FieldSubCategory.SubCategoryZ3);
                        break;
                }

                return new StandardValuesCollection(range);
            }
        }

        public TestExtender()
        {
        }

        public TestExtender(IContainer container)
        {
            container.Add(this);
        }

        public void SetFieldCategory(Component component, FieldCategory fieldCategory)
        {
            if (fieldCategories.ContainsKey(component)) {
                fieldCategories.Remove(component);
            }
            fieldCategories.Add(component, fieldCategory);

            SetFieldSubCategory(component, FieldSubCategory.None);
        }

        [DefaultValue(FieldCategory.None),
        Category("データ"),
        Description("入力項目のカテゴリを示す値を取得または設定します。")]
        public FieldCategory GetFieldCategory(Component component)
        {
            return fieldCategories.ContainsKey(component) ? fieldCategories[component] : FieldCategory.None;
        }

        public void SetFieldSubCategory(Component component, FieldSubCategory fieldSubCategory)
        {
            if (fieldSubCategories.ContainsKey(component)) {
                fieldSubCategories.Remove(component);
            }
            fieldSubCategories.Add(component, fieldSubCategory);
        }

        [DefaultValue(FieldSubCategory.None),
        Category("データ"),
        Description("入力項目のサブカテゴリを示す値を取得または設定します。"),
        TypeConverter(typeof(FieldSubCategoryConverter))]
        public FieldSubCategory GetFieldSubCategory(Component component)
        {
            return fieldSubCategories.ContainsKey(component) ? fieldSubCategories[component] : FieldSubCategory.None;
        }

        bool IExtenderProvider.CanExtend(object target)
        {
            if (target is Control && !(target is TestExtender)) {
                return true;
            }
            return false;
        }
    }
}



1

スキルアップ/キャリアアップ(JOB@IT)