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

时间:2009-09-03 10:42:29

标签: .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

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

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

虽然收藏编辑器(UITypeEditors)和其他设计时主题上有很多材料,但我找不到任何证明这种确切行为的链接,所以感谢任何帮助。

1 个答案:

答案 0 :(得分:4)

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

编辑:解决方案摘要

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

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

alt text http://i37.tinypic.com/154enpw.png

编辑器表单中的代码实际上仅用于UI,负责填充树,在预先选择的控件列表上设置检查,并在用户使用OK关闭表单时返回所选控件的列表。 / p>

接下来,我们有一个实现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文件中; download it here

正如我之前提到的,这只是一个快速的&amp;脏的解决方案仅供内部使用。尽管如此,我还是对任何改进建议表示赞赏。