Поддержка редактора во время разработки для коллекции элементов управления
Я хотел бы добавить свойство, представляющее коллекцию элементов управления для компонента, и иметь редактор коллекции, с помощью которого я могу легко выбирать элементы управления, принадлежащие коллекции. 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-файл; скачать его здесь.
Как я упоминал ранее, это было просто быстрое и грязное решение, предназначенное только для внутреннего использования. Все равно буду признателен за любые предложения по улучшению.