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

Я хотел бы добавить свойство, представляющее коллекцию элементов управления для компонента, и иметь редактор коллекции, с помощью которого я могу легко выбирать элементы управления, принадлежащие коллекции. VS делает почти то, что я хочу автоматически с помощью следующего кода:

    Private _controls As New List(Of Control)
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    Public ReadOnly Property SelectedControls() As List(Of Control)
        Get
            Return _controls
        End Get
    End Property

Я получаю по умолчанию CollectionEditor, могу добавлять и удалять элементы управления, и коллекция сериализуется.

Проблема в том, что я не хочу добавлять новые элементы управления, я хочу выбрать несколько элементов управления из других доступных элементов управления в форме. Есть ли какой-нибудь простой / стандартный способ сделать это, или мне придется написать свой собственный редактор коллекций и просмотреть коллекцию элементов управления?

Хотя есть много материалов по редакторам коллекций (UITypeEditors) и другим темам времени разработки, я не смог найти никаких ссылок, демонстрирующих это точное поведение, поэтому любая помощь приветствуется.

1 ответ

Решение

Хорошо, так что пока я обедал и сам писал редактор. Не было такого большого усилия. Я был бы рад поделиться, если это поможет.

Изменить: Сводка решения

Я написал редактор (см. Скриншот), который рекурсивно перечисляет все элементы управления, найденные в форме в виде дерева. Если для элементов управления установлены свойства "Текст" или "Изображение", отображается текст / изображение. Пользователь может выбрать несколько элементов управления с помощью флажков и даже отфильтровать список, чтобы отображать элементы управления только определенных типов.

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

http://i37.tinypic.com/154enpw.png

Код в форме редактора на самом деле предназначен только для пользовательского интерфейса, он отвечает за заполнение дерева, устанавливает проверки в списке предварительно выбранных элементов управления и возвращает список выбранных элементов управления, когда пользователь закрывает форму с помощью OK.

Далее у нас есть класс, который реализует UITypeEditor, который я назвал FormControlSelectionEditor. Этот класс присваивается свойствам, которые мы хотим использовать в редакторе для использования атрибута [Editor]. Это не намного больше, чем создание нового экземпляра формы при необходимости и отображение его в виде модального диалога.

Тогда есть сами свойства, которые имеют тип System.Collections.ObjectModel.ObservableCollection(Of Control). Я выбрал ObservableCollection, потому что мне нужно реагировать на изменения в списках также во время выполнения, но другие списки будут работать так же хорошо с незначительной адаптацией.

Одна вещь, которую я обнаружил, заключается в том, что я должен был написать свои свойства и редактор так, чтобы они использовали копии списков элементов управления. Другими словами, код UITypeEditor создает копию списка, сохраненного в свойстве, и передает его в форму редактора (для установки проверок при открытии формы), а когда форма закрывается, я очищаю список поддержки свойства и скопировать каждый элемент управления в списке, возвращенном из редактора. Я обнаружил, что в противном случае у меня были проблемы с сериализацией в файле.designer. Я не верю, что так должно быть; Я думаю, что это скорее ошибка с моей стороны.

Код для типичной собственности:

    Private WithEvents _insertButtons As New System.Collections.ObjectModel.ObservableCollection(Of Control)
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    <Editor(GetType(Design.FormControlSelectionEditor), GetType(UITypeEditor))> _
    Public Property InsertButtons() As System.Collections.ObjectModel.ObservableCollection(Of Control)
        Get
            Return _insertButtons
        End Get
        Set(ByVal value As System.Collections.ObjectModel.ObservableCollection(Of Control))
            If value Is Nothing Then
                RemoveInsertButtonEventHandlers(_insertButtons)
                _insertButtons.Clear()
            Else
                ' Copy the list items passed in into the internal list
                For i As Integer = _insertButtons.Count - 1 To 0 Step -1
                    If Not value.Contains(_insertButtons.Item(i)) Then _insertButtons.RemoveAt(i)
                Next
                For Each ctl As Control In value
                    If Not _insertButtons.Contains(ctl) Then _insertButtons.Add(ctl)
                Next
            End If
        End Set
    End Property
    Private Function ShouldSerializeInsertButtons() As Boolean
        Return _insertButtons.Count > 0
    End Function
    Private Sub ResetInsertButtons()
        InsertButtons = Nothing
    End Sub

Я поместил редактор в zip-файл; скачать его здесь.

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

Другие вопросы по тегам