オブジェクトのプロパティにカスタムのPropertyGrid中心の属性を追加して、より豊富な編集を提供し、いくつかの値を非表示にしてカテゴリにグループ化します。これは、使用しているクラスがそのような機能を提供せず、何もできないためです。それについて。
実際、コードを生成するのはMSのアプリケーション設定用であるため、プロパティごとにコードを拡張することはできません。私の他の質問を参照してください:RuntimeAppSettings.settingseditorダイアログ
オブジェクトのプロパティにカスタムのPropertyGrid中心の属性を追加して、より豊富な編集を提供し、いくつかの値を非表示にしてカテゴリにグループ化します。これは、使用しているクラスがそのような機能を提供せず、何もできないためです。それについて。
実際、コードを生成するのはMSのアプリケーション設定用であるため、プロパティごとにコードを拡張することはできません。私の他の質問を参照してください:RuntimeAppSettings.settingseditorダイアログ
他の人が示唆しているのとは異なり、それはかなり可能であり、それほど難しいことでもありません。たとえば、いくつかの新しい属性をいくつかのプロパティに追加したい場合、いくつかの基準に基づいて実行時に選択できます。
これを実装するために必要な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
。
ご覧のとおり、デフォルトの実装の一部の機能を毎回オーバーライドするだけなので、システムはかなり安定しており、期待どおりに動作するはずです。
豊富なカスタム PropertyGrid が必要な場合、代わりの設計は、CustomTypeDescriptor から継承するクラスで型をラップすることです。その後、GetProperties をオーバーライドして、基になるクラスのプロパティに PropertyGrid に必要な属性で注釈を付けることができます。
関連する質問への回答の詳細な説明https://stackoverflow.com/a/12586865/284795
[ExpandableObject] や [Editor] などの属性を、編集できないクラスのオブジェクトのプロパティに追加する必要がある場合は、プロパティのタイプに属性を追加できます。したがって、リフレクションを使用してオブジェクトを検査し、使用できます
TypeDescriptor.AddAttributes(typeof (*YourType*), new ExpandableObjectAttribute());
次に、タイプYourTypeのすべてのプロパティを属性で装飾したように動作します。