How do I inject a custom UITypeEditor for all properties of a closed-source type?

前端 未结 3 2008
无人及你
无人及你 2020-12-06 07:12

I want to avoid placing an EditorAttribute on every instance of a certain type that I\'ve written a custom UITypeEditor for.

I can\'t place an EditorAttribute on t

3条回答
  •  情深已故
    2020-12-06 07:42

    Marc's solution bluntly applies the EditorAttribute to the Bar type globally. If you have a delicate disposition, you might rather annotate properties of a specific instances. Alas, that isn't possible with TypeDescriptor.AddAttributes

    My solution was to write a wrapper ViewModel, which copies properties from T, annotating some with extra attributes. Suppose we have a variable datum of type Report, we'd use it like this

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

    Where ViewModel is defined:

    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);
        }
    }
    

    As defined above, this substitutes properties of a specific type, but you can substitute properties by name if you need the greater resolution.

提交回复
热议问题