好的,同时我已经吃过午饭并自己写了编辑器。没有那么大的努力。如果有帮助,我很乐意分享。
编辑:解决方案摘要
我写了一个编辑器(见截图),它递归地列出了在树视图中的表单上找到的所有控件。如果控件设置了它们的 Text 或 Image 属性,则显示文本/图像。用户可以使用复选框选择多个控件,甚至可以过滤列表以仅显示某些类型的控件。
(但我必须承认,由于这个编辑器仅供内部使用,我一般不会费心检查 image 属性,我只处理几个众所周知的控件类型。)
编辑器表单中的代码实际上只是针对 UI 的,负责填充树、设置对预选控件列表的检查以及在用户单击 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 文件中;在这里下载。
正如我之前提到的,这只是一个仅供内部使用的快速而肮脏的解决方案。尽管如此,我将不胜感激任何改进建议。