如何为闭源类型的所有属性注入自定义UITypeEditor?

我想避免在我编写自定义UITypeEditor的某个类型的每个实例上放置EditorAttribute。

我不能在类型上放置EditorAttribute,因为我无法修改源代码。

我引用了将要使用的唯一PropertyGrid实例。

我是否可以告诉PropertyGrid实例(或所有实例)在遇到特定类型时使用自定义UITypeEditor?

这是一篇MSDN文章,它提供了如何在.NET 2.0或更高版本中执行此操作的起点。

您通常可以通过TypeDescriptor.AddAttributes在运行时关联编辑器等。 例如( Bar属性应显示“……”,显示“Editing!”):

 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是不可能的

我的解决方案是编写一个包装器ViewModel ,它从T复制属性,用额外的属性注释一些。 假设我们有一个Report类型的可变datum ,我们就像这样使用它

  var pretty = ViewModel.DressUp(datum); pretty.PropertyAttributeReplacements[typeof(Smiley)] = new List() { new EditorAttribute(typeof(SmileyEditor),typeof(UITypeEditor))}; propertyGrid1.SelectedObject = pretty; 

定义ViewModel位置:

 public class ViewModel : CustomTypeDescriptor { private T _instance; private ICustomTypeDescriptor _originalDescriptor; public ViewModel(T instance, ICustomTypeDescriptor originalDescriptor) : base(originalDescriptor) { _instance = instance; _originalDescriptor = originalDescriptor; PropertyAttributeReplacements = new Dictionary>(); } public static ViewModel DressUp(T instance) { return new ViewModel(instance, TypeDescriptor.GetProvider(instance).GetTypeDescriptor(instance)); } ///  /// Most useful for changing EditorAttribute and TypeConvertorAttribute ///  public IDictionary> PropertyAttributeReplacements {get; set; } public override PropertyDescriptorCollection GetProperties (Attribute[] attributes) { var properties = base.GetProperties(attributes).Cast(); 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属性即可。