设计时编辑器对控件集合的支持

Tom*_*ens 5 .net user-controls design-time uitypeeditor collectioneditor

我想向组件添加一个表示控件集合的属性,并具有一个集合编辑器,通过它我可以轻松地选择属于该集合的控件。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
Run Code Online (Sandbox Code Playgroud)

我得到默认的CollectionEditor,可以添加和删除控件,并且集合被序列化。

问题是我不想添加控件,我想从表单上的其他可用控件中选择多个控件。有什么简单/标准的方法可以做到这一点,还是我必须编写自己的集合编辑器并运行控件集合?

尽管关于集合编辑器(UITypeEditors)和其他设计时主题的材料很多,但我找不到能够证明这种确切行为的任何链接,因此可以提供任何帮助。

Tom*_*ens 5

好的,所以同时我已经吃过午饭并自己写了编辑。没有那么大的努力。如果有帮助,我很乐意分享。

编辑:解决方案摘要

我写了一个编辑器(见截图),它递归地列出在树视图中的表单上找到的所有控件。如果控件设置了它们的文本或图像属性,则显示文本/图像。用户可以使用复选框选择多个控件,甚至可以过滤列表以仅显示某些类型的控件。

(不过,我必须承认,由于这个编辑器仅供内部使用,我没有费心检查图像属性,我只处理了几个众所周知的控件类型。)

替代文字

编辑器表单中的代码实际上只是用于 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
Run Code Online (Sandbox Code Playgroud)

我已将编辑器放入一个 zip 文件中;在这里下载

正如我之前提到的,这只是一个仅供内部使用的快速而肮脏的解决方案。尽管如此,我很感激任何改进建议。