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