【问题标题】:Design-time editor support for controls collection控件集合的设计时编辑器支持
【发布时间】:2010-11-25 06:05:32
【问题描述】:

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

【问题讨论】:

    标签: .net user-controls design-time uitypeeditor collectioneditor


    【解决方案1】:

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

    编辑:解决方案摘要

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

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

    【讨论】:

    • 可惜这只适用于Control。我正在尝试通过codeproject.com/Articles/687430/… 使用来自您工作的用户控件来实现相同的功能。我收到一个转换错误:无法将对象 [UserControl] 转换为 [Control] :(
    • 对不起 - 我在 2009 年写了这篇文章......并且必须承认我对当时的工作很着迷,但我真的无能为力了。如果其中任何一个仍然适用于当前工具,我实际上会感到惊讶。无论如何,祝你工作顺利。
    • 不用担心。我只需要鼓励用户更多地使用代码......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多