12

オブジェクトのプロパティにカスタムのPropertyGrid中心の属性を追加して、より豊富な編集を提供し、いくつかの値を非表示にしてカテゴリにグループ化します。これは、使用しているクラスがそのような機能を提供せず、何もできないためです。それについて。

実際、コードを生成するのはMSのアプリケーション設定用であるため、プロパティごとにコードを拡張することはできません。私の他の質問を参照してください:RuntimeAppSettings.settingseditorダイアログ

4

4 に答える 4

29

他の人が示唆しているのとは異なり、それはかなり可能であり、それほど難しいことでもありません。たとえば、いくつかの新しい属性をいくつかのプロパティに追加したい場合、いくつ基準に基づいて実行時に選択できます。

これを実装するために必要な2つのヘルパークラスがあります。

まず、他のプロパティをそのままにして、一部PropertyOverridingTypeDescriptorのプロパティに独自のプロパティ記述子を提供できるようにします。

public class PropertyOverridingTypeDescriptor : CustomTypeDescriptor
    {
        private readonly Dictionary<string, PropertyDescriptor> overridePds = new Dictionary<string, PropertyDescriptor>();

        public PropertyOverridingTypeDescriptor(ICustomTypeDescriptor parent)
            : base(parent)
        { }

        public void OverrideProperty(PropertyDescriptor pd)
        {
            overridePds[pd.Name] = pd;
        }

        public override object GetPropertyOwner(PropertyDescriptor pd)
        {
            object o = base.GetPropertyOwner(pd);

            if (o == null)
            {
                return this;
            }

            return o;
        }

        public PropertyDescriptorCollection GetPropertiesImpl(PropertyDescriptorCollection pdc)
        {
            List<PropertyDescriptor> pdl = new List<PropertyDescriptor>(pdc.Count+1);

            foreach (PropertyDescriptor pd in pdc)
            {
                if (overridePds.ContainsKey(pd.Name))
                {
                    pdl.Add(overridePds[pd.Name]);
                }
                else
                {
                    pdl.Add(pd);
                }
            }

            PropertyDescriptorCollection ret = new PropertyDescriptorCollection(pdl.ToArray());

            return ret;
        }

        public override PropertyDescriptorCollection GetProperties()
        {
            return GetPropertiesImpl(base.GetProperties());
        }
        public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            return GetPropertiesImpl(base.GetProperties(attributes));
        }
    }

いくつかの発言:

  • コンストラクターはICustomTypeDescriptor、ここで心配する必要はありません。任意のタイプのコンストラクターを取得TypeDescriptor.GetProvider(_settings).GetTypeDescriptor(_settings)できます。または、_settingsがそのタイプのいずれTypeかである可能性があるインスタンスです。object
  • OverrideProperty必要なことだけを実行します。後で詳しく説明します。

必要なもう1つのクラスはTypeDescriptionProvider、デフォルトの記述子の代わりにカスタムタイプ記述子を返すクラスです。ここにあります:

public class TypeDescriptorOverridingProvider : TypeDescriptionProvider
    {
        private readonly ICustomTypeDescriptor ctd;

        public TypeDescriptorOverridingProvider(ICustomTypeDescriptor ctd)
        {
            this.ctd = ctd;
        }

        public override ICustomTypeDescriptor GetTypeDescriptor (Type objectType, object instance)
        {
            return ctd;
        }
    }

かなり単純です。構築時に型記述子インスタンスを指定するだけで、ここに進みます。

そして最後に、コードを処理します。たとえば、ConnectionStringオブジェクト(またはタイプ)で終わるすべてのプロパティ_settingsをで編集できるようにしますSystem.Web.UI.Design.ConnectionStringEditor。これを実現するために、次のコードを使用できます。

// prepare our property overriding type descriptor
PropertyOverridingTypeDescriptor ctd = new PropertyOverridingTypeDescriptor(TypeDescriptor.GetProvider(_settings).GetTypeDescriptor(_settings));

// iterate through properies in the supplied object/type
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(_settings))
{
    // for every property that complies to our criteria
    if (pd.Name.EndsWith("ConnectionString"))
    {
        // we first construct the custom PropertyDescriptor with the TypeDescriptor's
        // built-in capabilities
        PropertyDescriptor pd2 =
            TypeDescriptor.CreateProperty(
                _settings.GetType(), // or just _settings, if it's already a type
                pd, // base property descriptor to which we want to add attributes
                    // The PropertyDescriptor which we'll get will just wrap that
                    // base one returning attributes we need.
                new EditorAttribute( // the attribute in question
                    typeof (System.Web.UI.Design.ConnectionStringEditor),
                    typeof (System.Drawing.Design.UITypeEditor)
                )
                // this method really can take as many attributes as you like,
                // not just one
            );

        // and then we tell our new PropertyOverridingTypeDescriptor to override that property
        ctd.OverrideProperty(pd2);
    }
}

// then we add new descriptor provider that will return our descriptor instead of default
TypeDescriptor.AddProvider(new TypeDescriptorOverridingProvider(ctd), _settings);

これで、で終わるすべてのプロパティは。ConnectionStringで編集できるようになりますConnectionStringEditor

ご覧のとおり、デフォルトの実装の一部の機能を毎回オーバーライドするだけなので、システムはかなり安定しており、期待どおりに動作するはずです。

于 2012-08-27T14:10:10.573 に答える
1

豊富なカスタム PropertyGrid が必要な場合、代わりの設計は、CustomTypeDescriptor から継承するクラスで型をラップすることです。その後、GetProperties をオーバーライドして、基になるクラスのプロパティに PropertyGrid に必要な属性で注釈を付けることができます。

関連する質問への回答の詳細な説明https://stackoverflow.com/a/12586865/284795

于 2012-09-25T20:26:07.240 に答える
1

[ExpandableObject] や [Editor] などの属性を、編集できないクラスのオブジェクトのプロパティに追加する必要がある場合は、プロパティのタイプに属性を追加できます。したがって、リフレクションを使用してオブジェクトを検査し、使用できます

TypeDescriptor.AddAttributes(typeof (*YourType*), new ExpandableObjectAttribute());

次に、タイプYourTypeのすべてのプロパティを属性で装飾したように動作します。

于 2014-04-15T08:59:23.907 に答える