【问题标题】:How to use an Items Collection Editor on a custom UserControl (.Net 4, Winforms)?如何在自定义用户控件(.Net 4,Winforms)上使用项目集合编辑器?
【发布时间】:2012-08-23 16:10:07
【问题描述】:

我创建了一个包含自定义ToolStrip ControlUserControl。在整个应用程序中使用UserControl 时,不能直接访问ToolStrip 控件,因为它在逻辑上嵌入在UserControl 中。

因此,为了访问ToolStrip 的项目,我在UserControl 类中定义了一个readonly 属性,该属性返回 ToolStrip 的项目。

现在,可以使用UserControl.Items 属性以编程方式编辑ToolStrip 的项目,但在设计模式下我不能这样做。

就像有人将UserControlToolBox拖到窗体,转到propertyGrid,选择项目的属性并相应地操作根深蒂固的ToolStrip的项目;就像我们在 Items Collection Editor 的帮助下处理任何标准的 ToolStrip 控件的项目集合一样。

这里,虽然UserControlItems属性显示在propertyGrid中,但无法使用,每次点击都会显示错误信息

值不能为空。参数名称:值

我确定这是因为该属性被声明为只读,我需要增加更多,以便在 propertyGrid 中单击它时,项目Collection Editor 会弹出ToolStrip 的项目并且可以因此处理。

那我该怎么做呢?

【问题讨论】:

    标签: c# .net vb.net winforms visual-studio-2010


    【解决方案1】:

    您可以通过暴露ToolStrip 本身来做到这一点,但这不是一个好主意。 UserControl 不应公开其内部控制。

    如果您的用户控件只有ToolStrip,您应该考虑使用CustomControl,它是一个继承ToolStrip 的类,您可以免费获得包括设计功能在内的所有功能。

    【讨论】:

    • 事实上,我的 UserControl 包含 ToolStrip 以外的其他控件。
    【解决方案2】:

    我研究这个问题已经有一段时间了,我得到的两个最普遍的想法是: 1) 将 ToolStrip 作为属性公开。 2) 为 UserControl 使用 ControlDesigner 并为 ToolStrip 设置 EnableDesignMode。

    但不知何故,它们都没有真正达到我的目的,因为暴露 ToolStrip 会让用户完全控制它,这不是我的目标。第二个选项甚至会让用户删除 ToolStrip。因此,我不得不想出一种不同的方法。就在那时,我发现了 CollectionBase 类。

    正如它所说,CollectionBase 类是强类型集合的抽象基类。那么如何通过它来维护 ToolStrip 项集合呢? 我创建了一个CollectionBase类的实例,并通过它来规范ToolStrip项的添加、修改、获取和删除。集合中的每个项目都来自从 ToolStripButton 类继承的类。这样,单个项目可以作为任何标准 ToolStripButton 处理,您可以相应地向用户隐藏或显示属性。最后,有问题的 ToolStrip 被设置为 CollectionBase 的父级,最终也成为每个 ToolStripItem 的父级。这是概念:

    Imports System.ComponentModel
    Imports System.Windows.Forms
    Imports Office2003
    Imports System.Drawing
    Imports System.Windows.Forms.Design
    
    Public Class MyUserControl
        Private _Buttons As MyUserControlButtons
        Public Event MyUserControlButtonClicked(ByVal Sender As MyUserControlButton)
    
        Public Sub New()
            MyBase.New()
    
            'This call is required by the Component Designer.
            InitializeComponent()
    
            _Buttons = New MyUserControlButtons(MyToolStrip)
        End Sub
    
        <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
        Public ReadOnly Property Buttons As MyUserControlButtons
            Get
                Return _Buttons
            End Get
        End Property
    
        Private Sub MyToolStrip_ItemClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ToolStripItemClickedEventArgs) Handles MyToolStrip.ItemClicked
         'Check if the ToolStrip item clicked is a ToolStripButton...
            If TypeOf e.ClickedItem Is ToolStripButton Then
                'Insert your code here...
    
             'Raise the custom event.
                RaiseEvent MyUserControlButtonClicked(Item)
            End If
        End Sub
    End Class
    
    #Region "Manager classes for MyUserControl buttons."
    
    Public Class MyUserControlButtons
        Inherits CollectionBase
        Private _Parent As ToolStrip
    
        ''' <summary>
        ''' Initializes a new instance of the MyUserControlButtons class.
        ''' </summary>
        ''' <param name="Holder">The ToolStrip that contains the items of the MyUserControlButtons class.</param>
        Public Sub New(ByVal Holder As ToolStrip)
            MyBase.New()
            _Parent = Holder
        End Sub
    
        ''' <summary>
        ''' The ToolStrip that contains this item.
        ''' </summary>
        Public ReadOnly Property Parent() As ToolStrip
            Get
                Return _Parent
            End Get
        End Property
    
        ''' <summary>
        ''' Gets the element at the specified index.
        ''' </summary>
        ''' <param name="Index">The zero-based index of the element to get.</param>
        Default Public ReadOnly Property Item(ByVal Index As Integer) As MyUserControlButton
            Get
                Return CType(List(Index), MyUserControlButton)
            End Get
        End Property
    
        ''' <summary>
        ''' Adds an item to the collection.
        ''' </summary>
        Public Function Add() As MyUserControlButton
            Return Me.Add
        End Function
    
        ''' <summary>
        ''' Adds an item to the collection.
        ''' </summary>
        ''' <param name="Value">The object to add to the collection.</param>
        Public Sub Add(ByVal Value As MyUserControlButton)
            List.Add(Value)
            Value.Parent = Me.Parent
        End Sub
    
        ''' <summary>
        ''' Adds an item to the collection.
        ''' </summary>
        ''' <param name="Name">The name of the object to add to the collection.</param>
        ''' <param name="Image">The image of the object to add to the collection.</param>
        Public Function Add(ByVal Name As String, ByVal Image As Image) As MyUserControlButton
            Dim b As MyUserControlButton = New MyUserControlButton(Me.Parent)
            b.Name = Name
            b.Text = Name
            b.Image = Image
            Me.Add(b)
            Return b
        End Function
    
        ''' <summary>
        ''' Adds an item to the collection.
        ''' </summary>
        ''' <param name="Name">The name of the object to add to the collection.</param>
        ''' <param name="Text">The text of the object to add to the collection.</param>
        ''' <param name="Image">The image of the object to add to the collection.</param>
        Public Function Add(ByVal Name As String, ByVal Text As String, ByVal Image As Image) As MyUserControlButton
            Dim b As MyUserControlButton = New MyUserControlButton(Me.Parent)
            b.Name = Name
            b.Text = Text
            b.Image = Image
            Me.Add(b)
            Return b
        End Function
    
        ''' <summary>
        ''' Removes the first occurence of a specific object from the collection.
        ''' </summary>
        ''' <param name="Value">The object to be removed.</param>
        Public Sub Remove(ByVal Value As MyUserControlButton)
            List.Remove(Value)
        End Sub
    
        ''' <summary>
        ''' Determines the index of a specific item in the collection.
        ''' </summary>
        ''' <param name="Value">The object to locate in the collection.</param>
        Public Function IndexOf(ByVal Value As Object) As Integer
            Return List.IndexOf(Value)
        End Function
    
        ''' <summary>
        ''' Determines whether the collection contains a specific value.
        ''' </summary>
        ''' <param name="Value">The object to locate in the collection.</param>
        Public Function Contains(ByVal Value As MyUserControlButton) As Boolean
            Return List.Contains(Value)
        End Function
    
        Protected Overrides Sub OnInsertComplete(ByVal index As Integer, ByVal value As Object)
            Dim b As MyUserControlButton = CType(value, MyUserControlButton)
            b.Parent = Me.Parent
            Me.Parent.Items.Insert(index, CType(value, ToolStripButton))
            MyBase.OnInsertComplete(index, value)
        End Sub
    
        Protected Overrides Sub OnSetComplete(ByVal index As Integer, ByVal oldValue As Object, ByVal newValue As Object)
            Dim b As MyUserControlButton = CType(newValue, MyUserControlButton)
            b.Parent = Me.Parent
            MyBase.OnSetComplete(index, oldValue, newValue)
        End Sub
    
        Protected Overrides Sub OnClearComplete()
            MyBase.OnClearComplete()
        End Sub
    End Class
    
    Public Class MyUserControlButton
        Inherits ToolStripButton
    
        ''' <summary>
        ''' Initializes a new instance of the MyUserControlButton class.
        ''' </summary>
        Sub New()
            MyBase.New()
            Init()
        End Sub
    
        ''' <summary>
        ''' Initializes a new instance of the MyUserControlButton class.
        ''' </summary>
        ''' <param name="Holder">The ToolStrip that contains the StackView button.</param>
        Sub New(ByVal Holder As ToolStrip)
            MyBase.New()
            Init()
            Me.Parent = Holder
        End Sub
    
        Private Sub Init()
            Me.AutoToolTip = False
            Me.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText
            Me.ImageAlign = ContentAlignment.MiddleLeft
            Me.ImageIndex = -1
            Me.ImageKey = ""
            Me.ImageTransparentColor = Color.Magenta
            Me.TextAlign = ContentAlignment.MiddleLeft
            Me.TextDirection = ToolStripTextDirection.Horizontal
        End Sub
    
        ''' <remarks>
        ''' Hide this property from the user in both design and code editor.
        ''' </remarks>
        <Browsable(False),
        EditorBrowsable(False)> _
        Public Shadows Property AccessibleDefaultActionDescription As String
            Get
                Return MyBase.AccessibleDefaultActionDescription
            End Get
            Set(ByVal value As String)
                MyBase.AccessibleDefaultActionDescription = value
            End Set
        End Property
    
        ''' <remarks>
        ''' Hide this property from the user in both design and code editor.
        ''' </remarks>
        <Browsable(False),
        EditorBrowsable(False)> _
        Public Shadows Property AccessibleDescription As String
            Get
                Return MyBase.AccessibleDescription
            End Get
            Set(ByVal value As String)
                MyBase.AccessibleDescription = value
            End Set
        End Property
    
        ''' <remarks>
        ''' Hide this property from the user in both design and code editor.
        ''' </remarks>
        <Browsable(False),
        EditorBrowsable(False)> _
        Public Shadows Property AccessibleName As String
            Get
                Return MyBase.AccessibleName
            End Get
            Set(ByVal value As String)
                MyBase.AccessibleName = value
            End Set
        End Property
    
    
        ' Keep on hiding the irrelevant properties...
    
    
        ''' <summary>
        ''' Gets or sets a value indicating whether default or custom ToolTip text is displayed on the ToolStripButton.
        ''' </summary>
        <DefaultValue(False)> _
        Public Shadows Property AutoToolTip As Boolean
            Get
                Return MyBase.AutoToolTip
            End Get
            Set(ByVal value As Boolean)
                MyBase.AutoToolTip = value
            End Set
        End Property
    
        ''' <summary>
        ''' Specifies whether the image and text are rendered.
        ''' </summary>
        <DefaultValue(GetType(ToolStripItemDisplayStyle), "ImageAndText")> _
        Public Overrides Property DisplayStyle As System.Windows.Forms.ToolStripItemDisplayStyle
            Get
                Return MyBase.DisplayStyle
            End Get
            Set(ByVal value As System.Windows.Forms.ToolStripItemDisplayStyle)
                MyBase.DisplayStyle = value
            End Set
        End Property
    
        ''' <summary>
        ''' The image that will be displayed on the control.
        ''' </summary>
        Public Overrides Property Image() As Image
            Get
                Return MyBase.Image
            End Get
            Set(ByVal value As Image)
                MyBase.Image = value
            End Set
        End Property
    
        ''' <summary>
        ''' Gets or sets the alignment of the image on a ToolStripItem.
        ''' </summary>
        <DefaultValue(GetType(ContentAlignment), "MiddleLeft")> _
        Public Shadows Property ImageAlign As ContentAlignment
            Get
                Return MyBase.ImageAlign
            End Get
            Set(ByVal value As ContentAlignment)
                MyBase.ImageAlign = value
            End Set
        End Property
    
        <EditorBrowsable(False),
        DefaultValue(-1)> _
        Public Shadows Property ImageIndex As Integer
            Get
                Return MyBase.ImageIndex
            End Get
            Set(ByVal value As Integer)
                MyBase.ImageIndex = value
            End Set
        End Property
    
        <EditorBrowsable(False),
        DefaultValue("")> _
        Public Shadows Property ImageKey As String
            Get
                Return MyBase.ImageKey
            End Get
            Set(ByVal value As String)
                MyBase.ImageKey = value
            End Set
        End Property
    
        ''' <summary>
        ''' Gets or sets the color to treat as transparent in a ToolStripItem image.
        ''' </summary>
        Public Shadows Property ImageTransparentColor As Color
            Get
                Return MyBase.ImageTransparentColor
            End Get
            Set(ByVal value As Color)
                MyBase.ImageTransparentColor = value
            End Set
        End Property
    
        ''' <summary>
        ''' Specifies the name used to identify the object.
        ''' </summary>
        Public Shadows Property Name() As String
            Get
                Return MyBase.Name
            End Get
            Set(ByVal value As String)
                MyBase.Name = value
            End Set
        End Property
    
        ''' <summary>
        ''' The ToolStrip that contains this item.
        ''' </summary>
        <Browsable(False)> _
        Public Shadows Property Parent As ToolStrip
            Get
                Return MyBase.Parent
            End Get
            Set(ByVal value As ToolStrip)
                MyBase.Parent = value
            End Set
        End Property
    
        ''' <summary>
        ''' The text that will be displayed on the control.
        ''' </summary>
        Public Overrides Property Text() As String
            Get
                Return MyBase.Text
            End Get
            Set(ByVal value As String)
                MyBase.Text = value
            End Set
        End Property
    
        ''' <summary>
        ''' Gets or sets the alignment of the text on a ToolStripLabel.
        ''' </summary>
        <DefaultValue(GetType(ContentAlignment), "MiddleLeft")> _
        Public Overrides Property TextAlign As ContentAlignment
            Get
                Return MyBase.TextAlign
            End Get
            Set(ByVal value As ContentAlignment)
                MyBase.TextAlign = value
            End Set
        End Property
    
        <Browsable(False),
        EditorBrowsable(False),
        DefaultValue(GetType(ToolStripTextDirection), "Horizontal")> _
        Public Overrides Property TextDirection As ToolStripTextDirection
            Get
                Return MyBase.TextDirection
            End Get
            Set(ByVal value As ToolStripTextDirection)
                MyBase.TextDirection = value
            End Set
        End Property
    
    
        ' Define other properties accordingly...
    End Class
    
    #End Region
    

    MyUserControl 是包含名为 MyToolStrip 的 ToolStrip 的自定义用户控件。 MyUserControlButtons 是从 CollectionBase 继承的类,MyUserControlButtons 的每一项都是从 ToolStripButton 继承的 MyUserControlButton 类的对象。

    在 MyUserControl 的构造函数中,MyUserControlButtons 被实例化为 MyToolStrip 作为其父级。通过从 MyUserControlButton 创建新对象,将项目添加到 MyUserControlButtons。要隐藏或显示的项目的属性在 MyUserControlButton 中进行管理。 MyUserControl 通过只读属性“Buttons”返回按钮列表。请注意“Buttons”属性的 DesignerSerializationVisibility 属性。它指定在设计时序列化组件上的属性时要使用的持久性类型。 'Content' 枚举成员告诉代码生成器为对象的内容生成代码,而不是为对象本身生成代码。

    这种方法的缺点是您在对 UserControl 执行复制粘贴时无法保留 ToolStrip 的项目。它仅在用户明确处理项目而不是在复制粘贴期间对内容进行序列化。任何关于如何处理它的想法都非常感谢。

    感谢所有的海报。虽然我应用了自己的概念,但您的想法为我铺平了道路。

    【讨论】:

      【解决方案3】:

      我有一个解决方案,但对于 c#

              [Editor("System.ComponentModel.Design.CollectionEditor, System.Design", typeof(UITypeEditor))]
          [MergableProperty(false)]
          [Category("Data")]
          [DescriptionAttribute("ToolStripItems")]
          public virtual ToolStripItemCollection ToolstripItems
          {
              get => toolStrip.Items;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-23
        • 1970-01-01
        • 2014-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-12
        相关资源
        最近更新 更多