如何在运行时将EditorAttribute(Editor)添加到对象的属性中?
我有My.Settings.ExcludeFiles
,由设置设计器创建为Public Property ExcludedFiles() As Global.System.Collections.Specialized.StringCollection
。通过属性网格编辑ExcludedFiles
时,“字符串集合编辑器”会生成“未找到类型'System.String'的构造函数”运行时异常。
我无法更改ExcludeFiles
属性的属性,因为下次进行任何设置更改时,它们都会被覆盖。因此,我必须在运行时附加/添加Editor / EditorAttribute。
我想要做的是在运行时添加StringCollectionEditor
,如下所示为设计时属性。
<Editor(GetType(StringCollectionEditor), GetType(UITypeEditor))> _
TypeDescriptor.AddAttributes( _
GetType(Specialized.StringCollection), _
New EditorAttribute( _
"System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", _
GetType(System.Drawing.Design.UITypeEditor)))
您只需添加一次此属性,例如应用程序初始化。
更灵活。见Nicolas Cadilhac 在Adding Editor / EditorAttribute at Run-time (Dynamically) to an Object's Property处回答以下问题。它使用派生的CustomTypeDescriptor和TypeDescriptionProvider类。您只需添加一次提供程序,例如应用程序初始化。
答案 0 :(得分:6)
在给出我的第一个答案之后,我记得Marc Gravell给出的另一个解决方案,我甚至评论过。信不信由你,你只需要调用TypeDescriptor.AddAttributes()。
这是:How do I inject a custom UITypeEditor for all properties of a closed-source type?。
对于你的情况,它给出了:
TypeDescriptor.AddAttributes(
typeof(StringCollection),
new EditorAttribute("System.Windows.Forms.Design.StringCollectionEditor,
System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
typeof(UITypeEditor)))
所以也许你应该取消我之前的答案,并确认这个作为解决方案(虽然所有的功劳都归功于Marc)。但是当你需要使用TypeDescriptor做更复杂的事情时,我之前的帖子仍然为你提供了一个很好的技巧。
答案 1 :(得分:0)
你做不到。只能在编译时定义属性(除非您当然动态生成类型)
答案 2 :(得分:0)
是的,可以动态更改TypeDescriptor,以便返回所需的UITypeEditor。这在article中有解释。但请注意,它会为此类型的所有属性添加它。
我从这里抓取代码并大致改变了以下内容:
private class StringCollectionTypeDescriptor : CustomTypeDescriptor
{
private Type _objectType;
private StringCollectionTypeDescriptionProvider _provider;
public StringCollectionTypeDescriptor(
StringCollectionTypeDescriptionProvider provider,
ICustomTypeDescriptor descriptor, Type objectType)
:
base(descriptor)
{
if (provider == null) throw new ArgumentNullException("provider");
if (descriptor == null)
throw new ArgumentNullException("descriptor");
if (objectType == null)
throw new ArgumentNullException("objectType");
_objectType = objectType;
_provider = provider;
}
/* Here is your customization */
public override object GetEditor(Type editorBaseType)
{
return new MultilineStringEditor();
}
}
public class StringCollectionTypeDescriptionProvider : TypeDescriptionProvider
{
private TypeDescriptionProvider _baseProvider;
public StringCollectionTypeDescriptionProvider(Type t)
{
_baseProvider = TypeDescriptor.GetProvider(t);
}
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
return new StringCollectionTypeDescriptor(this, _baseProvider.GetTypeDescriptor(objectType, instance), objectType);
}
}
然后注册您的提供者:
TypeDescriptor.AddProvider(new StringCollectionTypeDescriptionProvider
(typeof(System.Collections.Specialized.StringCollection)),
typeof(System.Collections.Specialized.StringCollection));
这很有效,除了它会让你发现你有另一个问题:MultilineStringEditor是一个使用String类型的编辑器,而不是StringCollection类型。您实际需要的是.Net框架中的私有StringCollectionEditor。所以让我们用以下方法替换GetEditor:
public override object GetEditor(Type editorBaseType)
{
Type t = Type.GetType("System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
return TypeDescriptor.CreateInstance(null, t, new Type[] { typeof(Type) }, new object[] { typeof(string) });
}
我希望这会有所帮助。