3

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

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

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

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

这里,虽然显示的Items属性UserControl在 中propertyGrid,但不能使用,每次点击都会显示错误信息

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

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

那么我应该怎么做呢?

4

3 回答 3

3

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

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

于 2012-08-23T16:15:12.653 回答
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 属性。它指定在设计时序列化组件上的属性时要使用的持久性类型。“内容”枚举成员告诉代码生成器为对象的内容生成代码,而不是为对象本身生成代码。

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

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

于 2012-09-15T15:49:20.460 回答
0

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

        [Editor("System.ComponentModel.Design.CollectionEditor, System.Design", typeof(UITypeEditor))]
    [MergableProperty(false)]
    [Category("Data")]
    [DescriptionAttribute("ToolStripItems")]
    public virtual ToolStripItemCollection ToolstripItems
    {
        get => toolStrip.Items;
    }
于 2020-01-24T09:53:54.407 回答