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
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.