Поддержка редактора времени разработки для коллекции элементов управления
-
21-09-2019 - |
Вопрос
Я хотел бы добавить свойство, представляющее коллекцию элементов управления, к компоненту и иметь редактор коллекций, с помощью которого я мог бы легко выбирать элементы управления, принадлежащие коллекции.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
Я получаю редактор коллекций по умолчанию, могу добавлять и удалять элементы управления, и коллекция сериализуется.
Проблема в том, что я не хочу добавлять новое элементы управления, я хочу выбрать несколько элементов управления из других доступных элементов управления в форме.Есть ли какой-нибудь простой / стандартный способ сделать это, или мне придется написать свой собственный редактор коллекций и запустить через коллекцию элементов управления?
Хотя существует множество материалов по редакторам коллекций (UITypeEditors) и другим темам, связанным с разработкой, я не смог найти никаких ссылок, демонстрирующих именно это поведение, поэтому приветствуется любая помощь.
Решение
Итак, тем временем я пообедал и сам написал редактору.Это было не такое уж большое усилие.Я был бы рад поделиться, если это поможет.
Редактировать:Краткое описание решения
Я написал редактор (см. Скриншот), который рекурсивно перечисляет все элементы управления, найденные в форме, в виде дерева.Если для элементов управления заданы свойства текста или изображения, отображается текст / изображение.Пользователь может выбрать несколько элементов управления с помощью флажков и даже отфильтровать список, чтобы отображать только элементы управления определенных типов.
(Однако я должен признать, что, поскольку этот редактор предназначался только для внутреннего использования, я не стал утруждать себя проверкой свойства image в общем виде, я просто обрабатываю пару хорошо известных типов элементов управления.)
Код в форме редактора на самом деле предназначен только для пользовательского интерфейса, отвечает за заполнение дерева, установку проверок в списке предварительно выбранных элементов управления и возврат списка выбранных элементов управления, когда пользователь закрывает форму с помощью кнопки OK.
Далее, у нас есть класс, который реализует UITypeEditor, который я назвал FormControlSelectionEditor .Этот класс присваивается свойствам, которые мы хотим использовать в редакторе для использования атрибута [Editor].Это не намного больше, чем создать новый экземпляр формы, когда требуется, и отобразить его в виде модального диалогового окна.
Затем есть сами свойства, которые относятся к типу System.Коллекции.Объектная модель.Наблюдаемая коллекция (элемента управления).Я выбрал 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-файл; скачать его можно здесь.
Как я упоминал ранее, это было просто быстрое и грязное решение, предназначенное только для внутреннего использования.Тем не менее, я был бы признателен за любые предложения по улучшению.