2009-05-11 10 views
8

Quiero evitar colocar un EditorAtributo en cada instancia de un cierto tipo para el que he escrito un UITypeEditor personalizado.¿Cómo puedo inyectar un UITypeEditor personalizado para todas las propiedades de un tipo de fuente cerrada?

No puedo colocar un EditorAtributo en el tipo porque no puedo modificar el origen.

Tengo una referencia a la única instancia de PropertyGrid que se utilizará.

¿Puedo decirle a una instancia de PropertyGrid (o a todas las instancias) que use un UITypeEditor personalizado siempre que encuentre un tipo específico?

Here es un artículo de MSDN que proporciona un punto de partida sobre cómo hacer esto en .NET 2.0 o superior.

Respuesta

16

Por lo general, puede asociar editores, etc. en tiempo de ejecución a través de TypeDescriptor.AddAttributes. Por ejemplo (la propiedad Bar debe mostrar con un "..." que muestra 'Edición'): solución

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() } } }); 
    } 
} 
+0

Marc, bien hecho. Hubiera recomendado crear un descriptor de tipo personalizado y el proveedor para publicarlo, pero su método es un buen atajo para registrar el proveedor detrás de la escena e inyectar el editor. Aprendí algo. –

+0

Guau, eso es muy simple en la práctica. ¡Gracias! –

+0

¡Esto es perfecto! Estoy trabajando en una biblioteca de dibujo y quería proporcionar compatibilidad con el editor de PropertyGrid para objetos sin tomar una dependencia de Windows Forms de la biblioteca de objetos para decorar las propiedades. Esta solución me permite crear editores fuera de la biblioteca principal y agregarlos en tiempo de ejecución. –

0

Solo agregue un Editor attribute a su clase.

+2

Excelente idea, pero olvidé mencionar que no puedo colocar un EditorAtributo en el tipo porque no puedo modificar el código fuente. –

3

de Marc rodeos aplica la EditorAttribute a la barra de tipo a nivel mundial. Si tiene una disposición delicada, puede anotar las propiedades de instancias específicas. Por desgracia, eso no es posible con TypeDescriptor.AddAttributes

Mi solución fue escribir un contenedor ViewModel<T>, que copia las propiedades de T, anotando algunas con atributos adicionales. Supongamos que tenemos una variable datum del tipo de informe, nos gustaría utilizar de esta manera

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

Dónde ViewModel<T> se define:

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

Como se definió anteriormente, este sustituye propiedades de un tipo específico, pero puede sustituir propiedades por nombre si necesita la mayor resolución.

+0

Ya que decidió que esto es demasiado faff, y para usar la solución global mucho más simple. –

+0

Volví a usar esto, pero ADVERTENCIA podría ser incompatible con objetos que implementan ICustomTypeDescriptor –

Cuestiones relacionadas