如何为闭源类型的所有属性注入自定义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属性即可。