Как добавить пользовательский UITypeEditor для всех свойств типа с закрытым исходным кодом? - PullRequest
8 голосов
/ 11 мая 2009

Я хочу избежать размещения EditorAttribute на каждом экземпляре определенного типа, для которого я написал пользовательский UITypeEditor.

Я не могу разместить атрибут EditorAttribute для типа, поскольку не могу изменить источник.

У меня есть ссылка на единственный экземпляр PropertyGrid, который будет использоваться.

Могу ли я указать экземпляру PropertyGrid (или всем экземплярам) использовать пользовательский UITypeEditor всякий раз, когда он встречает определенный тип?

Здесь - это статья MSDN, которая предоставляет отправную точку для того, как сделать это в .NET 2.0 или более поздней версии.

Ответы [ 3 ]

18 голосов
/ 11 мая 2009

Обычно вы можете связать редакторов и т. Д. Во время выполнения через TypeDescriptor.AddAttributes. Например (свойство Bar должно отображаться с «...», которое отображает «Редактирование!»):

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() } } });
    }
}
3 голосов
/ 25 сентября 2012

Решение Марка прямо применяет EditorAttribute к типу Bar глобально. Если у вас деликатный характер, вы можете скорее аннотировать свойства конкретных экземпляров. Увы, это невозможно с TypeDescriptor.AddAttributes

Мое решение было написать обертку ViewModel<T>, которая копирует свойства из T, помечая некоторые дополнительными атрибутами. Предположим, у нас есть переменная datum типа Report, мы будем использовать ее следующим образом

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

Где ViewModel<T> определяется:

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

Как определено выше, это заменяет свойства определенного типа, но вы можете заменить свойства по имени, если вам нужно большее разрешение.

0 голосов
/ 11 мая 2009

Просто добавьте атрибут Editor * в свой класс.

...