我想避免在我为其编写自定义 UITypeEditor 的特定类型的每个实例上放置 EditorAttribute。
我无法在类型上放置 EditorAttribute,因为我无法修改源。
我引用了将要使用的唯一 PropertyGrid 实例。
我可以告诉 PropertyGrid 实例(或所有实例)在遇到特定类型时使用自定义 UITypeEditor 吗?
这是一篇 MSDN 文章,提供了如何在 .NET 2.0 或更高版本中执行此操作的起点。
我想避免在我为其编写自定义 UITypeEditor 的特定类型的每个实例上放置 EditorAttribute。
我无法在类型上放置 EditorAttribute,因为我无法修改源。
我引用了将要使用的唯一 PropertyGrid 实例。
我可以告诉 PropertyGrid 实例(或所有实例)在遇到特定类型时使用自定义 UITypeEditor 吗?
这是一篇 MSDN 文章,提供了如何在 .NET 2.0 或更高版本中执行此操作的起点。
您通常可以在运行时通过TypeDescriptor.AddAttributes
. 例如(该Bar
属性应显示“...”,显示“正在编辑!”):
using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
class Foo
{
public Foo() { Bar = new Bar(); }
public Bar Bar { get; set; }
}
class Bar
{
public string Value { get; set; }
}
class BarEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
MessageBox.Show("Editing!");
return base.EditValue(context, provider, value);
}
}
static class Program
{
[STAThread]
static void Main()
{
TypeDescriptor.AddAttributes(typeof(Bar),
new EditorAttribute(typeof(BarEditor), typeof(UITypeEditor)));
Application.EnableVisualStyles();
Application.Run(new Form { Controls = { new PropertyGrid { SelectedObject = new Foo() } } });
}
}
Marc 的解决方案直言将 EditorAttribute 应用于全局的 Bar 类型。如果您有一个微妙的性格,您可能宁愿注释特定实例的属性。唉,这是不可能的 TypeDescriptor.AddAttributes
我的解决方案是编写一个 wrapper ViewModel<T>
,它从 T 复制属性,用额外的属性注释一些。假设我们有一个datum
报表类型的变量,我们会像这样使用它
var pretty = ViewModel<Report>.DressUp(datum);
pretty.PropertyAttributeReplacements[typeof(Smiley)] = new List<Attribute>() { new EditorAttribute(typeof(SmileyEditor),typeof(UITypeEditor))};
propertyGrid1.SelectedObject = pretty;
在哪里ViewModel<T>
定义:
public class ViewModel<T> : CustomTypeDescriptor
{
private T _instance;
private ICustomTypeDescriptor _originalDescriptor;
public ViewModel(T instance, ICustomTypeDescriptor originalDescriptor) : base(originalDescriptor)
{
_instance = instance;
_originalDescriptor = originalDescriptor;
PropertyAttributeReplacements = new Dictionary<Type,IList<Attribute>>();
}
public static ViewModel<T> DressUp(T instance)
{
return new ViewModel<T>(instance, TypeDescriptor.GetProvider(instance).GetTypeDescriptor(instance));
}
/// <summary>
/// Most useful for changing EditorAttribute and TypeConvertorAttribute
/// </summary>
public IDictionary<Type,IList<Attribute>> PropertyAttributeReplacements {get; set; }
public override PropertyDescriptorCollection GetProperties (Attribute[] attributes)
{
var properties = base.GetProperties(attributes).Cast<PropertyDescriptor>();
var bettered = properties.Select(pd =>
{
if (PropertyAttributeReplacements.ContainsKey(pd.PropertyType))
{
return TypeDescriptor.CreateProperty(typeof(T), pd, PropertyAttributeReplacements[pd.PropertyType].ToArray());
}
else
{
return pd;
}
});
return new PropertyDescriptorCollection(bettered.ToArray());
}
public override PropertyDescriptorCollection GetProperties()
{
return GetProperties(null);
}
}
如上所述,这会替换特定类型的属性,但如果您需要更高的分辨率,可以按名称替换属性。
只需将Editor 属性添加到您的类。