2009-05-11 4 views
8

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

Я не могу поместить EditorAttribute в тип, потому что я не могу изменить источник.

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

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

Here является статьей MSDN, которая представляет собой отправную точку в том, как это сделать в .NET 2.0 или выше.

ответ

16

Обычно вы можете связывать редакторов и т. Д. Во время выполнения через 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() } } }); 
    } 
} 
+0

Марк, молодец. Я бы посоветовал создать дескриптор пользовательского типа и поставщика, чтобы опубликовать его, но ваш метод является хорошим ярлыком для регистрации провайдера за сценой и ввода редактора! Узнал что-то. –

+0

Ничего себе, это очень просто на практике. Благодаря! –

+0

Это прекрасно! Я работаю над библиотекой чертежей и хочу предоставить поддержку редактора PropertyGrid для объектов, не принимая зависимость от Windows Forms от библиотеки объектов, чтобы украсить свойства. Это решение позволяет мне создавать редакторы вне основной библиотеки и добавлять их во время выполнения. –

0

Просто добавьте Editor attribute в ваш класс.

+2

Отличная идея, но я забыл упомянуть, что я не могу поместить EditorAttribute в тип, потому что я не могу изменить источник. –

3

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

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

 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

С тех пор решил, что это слишком много, и использовать гораздо более простое глобальное решение. –

+0

Вернулся к использованию этого, но ПРЕДУПРЕЖДЕНИЕ может быть несовместимо с объектами, реализующими ICustomTypeDescriptor –

 Смежные вопросы

  • Нет связанных вопросов^_^