Como faço para injetar um UITypeEditor personalizado para todas as propriedades de um tipo de código fechado?

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

Pergunta

Eu quero evitar colocar um EditorAttribute em cada instância de um certo tipo que eu escrevi um UITypeEditor personalizado para.

Eu não posso colocar um EditorAttribute do tipo, porque não posso modificar a fonte.

Eu tenho uma referência à única instância PropertyGrid que será usado.

Posso contar uma instância PropertyGrid (ou todas as instâncias) para usar um UITypeEditor costume sempre que encontra um tipo específico?

Aqui é um artigo do MSDN que fornece estão começando ponto como fazer isso no .NET 2.0 ou superior.

Foi útil?

Solução

Você pode editores normalmente associados etc em tempo de execução via TypeDescriptor.AddAttributes. Por exemplo (a propriedade Bar deve mostrar com um "..." que exibe "Edição!"):

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

Outras dicas

A solução de Marc sem rodeios aplica o EditorAttribute ao tipo Bar globalmente. Se você tem uma disposição delicado, você pode propriedades bastante anotar de um instâncias específicas. Infelizmente, isso não é possível com TypeDescriptor.AddAttributes

Minha solução foi a escrever uma ViewModel<T> invólucro, que copia propriedades de T, anotando alguns com atributos extras. Suponha que temos um datum variável do tipo Report, nós usá-lo como este

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

Onde ViewModel<T> está definida:

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 definido acima, este substitutos propriedades de um tipo específico, mas você pode substituir propriedades pelo nome, se você precisa a resolução maior.

Basta adicionar um Editor de atributo na sua classe.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top