我想一些自定义的PropertyGrid为中心的属性添加到该对象的属性,为客户提供更丰富的编辑,隐藏类别的一些价值观和他们组,因为该类我的工作并没有提供这样的功能,我不能做任何事情关于它。
真的,它是生成代码MS的应用程序设置,这样你就可以以任何方式财产明智不会延长。 见我的其他问题: 运行AppSettings.settings编辑器对话框
我想一些自定义的PropertyGrid为中心的属性添加到该对象的属性,为客户提供更丰富的编辑,隐藏类别的一些价值观和他们组,因为该类我的工作并没有提供这样的功能,我不能做任何事情关于它。
真的,它是生成代码MS的应用程序设置,这样你就可以以任何方式财产明智不会延长。 见我的其他问题: 运行AppSettings.settings编辑器对话框
不像其他人所说,这是完全可能的,也并不难。 例如,你想一些新的属性添加到一些属性,你可以根据某些条件在运行时进行选择。
还有就是我们需要实现这两个辅助类。
首先去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
不正是我们所需要的,更多的后来。 我们需要的其他类是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
。
正如你所看到的,我们只是覆盖默认实现的一些功能每一次,所以系统应该是相当稳定的,像预期的那样。
如果你需要添加像[ExpandableObject]或[编辑]对类,你不能修改您可以将属性添加到属性的类型对象的属性属性。 所以,你可以使用反射来检查对象,并使用
TypeDescriptor.AddAttributes(typeof (*YourType*), new ExpandableObjectAttribute());
然后,它像你装饰的属性类型YourType的所有属性。
如果你想定制丰富的PropertyGrid,另一种设计是为了让你的包裹你的类型,一类从CustomTypeDescriptor继承。 然后,您可以覆盖的GetProperties,标注有需要的PropertyGrid属性的基础类的属性。
一个相关的问题回答中详细描述https://stackoverflow.com/a/12586865/284795
接受答案的工作,但它也有缺陷:如果您指定的供应商基类,它也是会工作的派生类,但是,由于PropertyOverridingTypeDescriptor
父(从中会得到它的属性)是基类型,派生类型只能找到的基类的属性。 这导致了Havok在例如,设计师的WinForms(并可能导致你,如果你使用的是数据丢失TypeDescriptor
序列化的数据)。
只是为了记录在案,我做了基于@ GMAN的答案一个通用的解决方案,我已经张贴在这里作为解决自己的问题(这是一个不同的问题,但解决方案使用此一个能用的)。