¿Cómo me inyecto una UITypeEditor personalizado para todas las propiedades de un tipo de código cerrado?

StackOverflow https://stackoverflow.com/questions/849202

Pregunta

Quiero evitar la colocación de un EditorAttribute en cada instancia de un determinado tipo que he escrito un UITypeEditor personalizado para.

No puedo colocar un EditorAttribute del tipo porque no puedo modificar el código fuente.

I tiene una referencia a la única instancia PropertyGrid que será utilizado.

¿Puedo contar una instancia PropertyGrid (o todas las instancias) para utilizar un UITypeEditor costumbre cada vez que se encuentra con un tipo específico?

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

¿Fue útil?

Solución

Normalmente se puede asociar editores, etc. en tiempo de ejecución a través de TypeDescriptor.AddAttributes. Por ejemplo (la Bar propiedad debe mostrar con un "..." que muestra 'Edició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() } } });
    }
}

Otros consejos

La solución de Marc aplica sin rodeos la EditorAttribute a la barra de tipo a nivel mundial. Si usted tiene una disposición delicada, es posible que en lugar de anotar propiedades a casos específicos. Por desgracia, eso no es posible con TypeDescriptor.AddAttributes

Mi solución fue escribir un envoltorio ViewModel<T>, que copia las propiedades de T, anotando algunos 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;

Donde <=> 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 se puede sustituir propiedades por su nombre si necesita mayor resolución.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top