5

我想向组件添加一个表示控件集合的属性,并有一个集合编辑器,我可以使用它轻松选择属于该集合的控件。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) 和其他设计时主题的材料,但我无法找到任何链接来演示这种确切的行为,因此感谢您提供任何帮助。

4

1 回答 1

5

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

编辑:解决方案摘要

我写了一个编辑器(见截图),它递归地列出了在树视图中的表单上找到的所有控件。如果控件设置了它们的 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 文件中;在这里下载

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

于 2009-09-03T14:23:00.863 回答