Добавление атрибута Editor / EditorAttribute во время выполнения (динамически) к свойству объекта

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

Вопрос

Как добавить атрибут EditorAttribute (Редактор) к свойству объекта во время выполнения?

У меня есть My.Settings.ExcludeFiles, который создается дизайнером настроек как Public Property ExcludedFiles() As Global.System.Collections.Specialized.StringCollection.При редактировании ExcludedFiles с помощью таблицы свойств "Редактор коллекции строк" генерирует исключение времени выполнения "Конструктор типа 'System.Строка'не найдена".

Я не могу изменить атрибуты ExcludeFiles свойство, потому что они будут перезаписаны при следующем внесении каких-либо изменений в настройки.Следовательно, я должен прикрепить /добавить атрибут Editor / EditorAttribute во время выполнения.

То, что я хочу сделать, это добавить StringCollectionEditor во время выполнения, показанный ниже как атрибут времени разработки.

    <Editor(GetType(StringCollectionEditor), GetType(UITypeEditor))> _

Решения

Способ №1

TypeDescriptor.AddAttributes( _
    GetType(Specialized.StringCollection), _
    New EditorAttribute( _
        "System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", _
         GetType(System.Drawing.Design.UITypeEditor)))

Вам нужно добавить этот атрибут только один раз, например при инициализации приложения.

Способ №2

Более гибкий.Смотрите Николаса Кадильяка ответ ниже по адресу Добавление атрибута Editor / EditorAttribute во время выполнения (динамически) к свойству объекта.Он использует производные классы CustomTypeDescriptor и TypeDescriptionProvider.Вам нужно добавить поставщика только один раз, например, при инициализации приложения.

Это было полезно?

Решение

Дав вам свой первый ответ, я вспомнил другое решение, данное Марком Гравеллом, которое я даже прокомментировал.Хотите верьте, хотите нет, но вам просто нужно вызвать TypeDescriptor .addAttributes() .

Это здесь: Как мне внедрить пользовательский UITypeEditor для всех свойств типа с закрытым исходным кодом?.

Для вашего случая это дает:

TypeDescriptor.AddAttributes(
    typeof(StringCollection),
    new EditorAttribute("System.Windows.Forms.Design.StringCollectionEditor,
        System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
        typeof(UITypeEditor)))

Так что, возможно, вам следует снять галочку с моего предыдущего ответа и подтвердить этот как решение (хотя вся заслуга принадлежит Марку).Но мой предыдущий пост по-прежнему дает вам хорошую технику, когда вам нужно делать более сложные вещи с помощью TypeDescriptor.

Другие советы

Ты не можешь.Атрибут может быть определен только во время компиляции (если, конечно, вы не генерируете тип динамически).

Да, можно динамически изменять TypeDescriptor так, чтобы вы возвращали нужный вам UITypeEditor.Это объясняется в этом Статья.Но обратите внимание, что он добавит его для всех свойств этого типа.

Я взял код отсюда и грубо изменил его на следующий:

private class StringCollectionTypeDescriptor : CustomTypeDescriptor
{
    private Type _objectType;
    private StringCollectionTypeDescriptionProvider _provider;

    public StringCollectionTypeDescriptor(
        StringCollectionTypeDescriptionProvider provider,
        ICustomTypeDescriptor descriptor, Type objectType)
        :
        base(descriptor)
    {
        if (provider == null) throw new ArgumentNullException("provider");
        if (descriptor == null)
            throw new ArgumentNullException("descriptor");
        if (objectType == null)
            throw new ArgumentNullException("objectType");
        _objectType = objectType;
        _provider = provider;
    }

    /* Here is your customization */
    public override object GetEditor(Type editorBaseType)
    {
        return new MultilineStringEditor();
    }
}

public class StringCollectionTypeDescriptionProvider : TypeDescriptionProvider
{
    private TypeDescriptionProvider _baseProvider;

    public StringCollectionTypeDescriptionProvider(Type t)
    {
        _baseProvider = TypeDescriptor.GetProvider(t);
    }

    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
    {
        return new StringCollectionTypeDescriptor(this, _baseProvider.GetTypeDescriptor(objectType, instance), objectType);
    }
}

Затем вы регистрируете своего провайдера:

TypeDescriptor.AddProvider(new StringCollectionTypeDescriptionProvider
    (typeof(System.Collections.Specialized.StringCollection)),
    typeof(System.Collections.Specialized.StringCollection));

Это работает хорошо, за исключением того, что это заставит вас обнаружить, что у вас есть другая проблема:MultilineStringEditor - это редактор, который работает с типом String, а не с типом StringCollection.Что вам на самом деле нужно, так это частный StringCollectionEditor в .Net framework.Итак, давайте заменим GetEditor на:

public override object GetEditor(Type editorBaseType)
{
    Type t = Type.GetType("System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
    return TypeDescriptor.CreateInstance(null, t, new Type[] { typeof(Type) }, new object[] { typeof(string) });
}

Я надеюсь, что это поможет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top