Come faccio a iniettare un UITypeEditor personalizzato per tutte le proprietà di un tipo closed-source?

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

Domanda

Voglio evitare di mettere un EditorAttribute su ogni istanza di un certo tipo che ho scritto un UITypeEditor personalizzato per.

Non riesco a effettuare un EditorAttribute del tipo perché non posso modificare il sorgente.

Ho un riferimento all'unica istanza PropertyGrid che verrà utilizzato.

Posso dire un'istanza PropertyGrid (o tutte le istanze) per utilizzare un UITypeEditor personalizzato ogni volta che incontra un tipo specifico?

Qui è un articolo di MSDN che fornisce sono punto di partenza su come fare questo in .NET 2.0 o superiore.

È stato utile?

Soluzione

In genere è possibile associare i redattori ecc in fase di esecuzione tramite TypeDescriptor.AddAttributes. Per esempio (la Bar proprietà deve dimostrare con un "..." che visualizza 'Modifica'):

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

Altri suggerimenti

La soluzione di Marc applica senza mezzi termini l'EditorAttribute al bar tipo a livello mondiale. Se si dispone di una disposizione delicata, si potrebbe piuttosto annotare proprietà di uno specifico istanze. Purtroppo, ciò non è possibile con TypeDescriptor.AddAttributes

La mia soluzione era di scrivere un wrapper ViewModel<T>, che copia oggetti di T, annotando alcuni con attributi extra. Supponiamo di avere una variabile di tipo datum relazione, saremmo usare in questo modo

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

Dove <=> è definito:

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

Come sopra definito, questo sostituisce proprietà di un tipo specifico, ma si può sostituire immobili per nome se è necessario maggiore risoluzione.

Basta aggiungere un Editor attribuiscono al tuo classe.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top