Comment puis-je injecter un UITypeEditor personnalisé pour toutes les propriétés d'un type source fermé?

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

Question

Je veux éviter de placer un EditorAttribute sur tous les cas d'un certain type que j'ai écrit un UITypeEditor personnalisé pour.

Je ne peux pas passer une EditorAttribute du type parce que je ne peux pas modifier la source.

J'ai une référence à la seule instance PropertyGrid qui sera utilisé.

Puis-je dire une instance PropertyGrid (ou toutes les instances) d'utiliser un UITypeEditor personnalisé chaque fois qu'il rencontre un type spécifique?

est un article MSDN qui fournit sont le point de départ sur comment faire cela dans .NET 2.0 ou plus.

Était-ce utile?

La solution

Vous pouvez associer habituellement les éditeurs etc lors de l'exécution via TypeDescriptor.AddAttributes. Par exemple (la propriété doit montrer Bar avec « ... » qui affiche « Edition »):

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

Autres conseils

La solution de Marc applique brutalement le EditorAttribute au barreau de type dans le monde. Si vous avez une disposition délicate, vous pourriez plutôt annoter propriétés d'un cas précis. Hélas, cela est impossible avec TypeDescriptor.AddAttributes

Ma solution a été d'écrire un wrapper ViewModel<T>, qui copie les propriétés de T, annoter certains avec des attributs supplémentaires. Supposons que nous ayons une variable du rapport de datum de type, nous aimerions l'utiliser comme ceci

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

Où est défini <=>:

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

Comme défini ci-dessus, ce substitue les propriétés d'un type particulier, mais vous pouvez remplacer les propriétés par nom si vous avez besoin une plus grande résolution.

Il suffit d'ajouter un Editor attribut à votre classe.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top