[英]How to use an Items Collection Editor on a custom UserControl (.Net 4, Winforms)?
我創建了一個包含自定義ToolStrip Control
的UserControl
。 在整個應用程序中使用UserControl
,不能直接訪問ToolStrip
控件,因為它在邏輯上嵌入在UserControl
。
因此,為了訪問ToolStrip
的項目,我在UserControl
類中定義了一個readonly
屬性,該屬性返回 ToolStrip 的項目。
現在,可以使用UserControl.Items
屬性以編程方式編輯ToolStrip
的項目,但我無法在設計模式下執行相同操作。
就像有人將UserControl
從ToolBox
拖到窗體上,轉到propertyGrid
,選擇 Item 的屬性並相應地操作根深蒂固的ToolStrip
的項目; 就像我們在項目Collection Editor
的幫助下處理任何標准ToolStrip
控件的項目集合一樣。
這里,雖然UserControl
的Items
屬性顯示在propertyGrid
,但它不可用,每次單擊時都會顯示錯誤消息
值不能為空。 參數名稱:值
我確定這是因為該屬性被聲明為只讀,我需要更多地加息,以便在 propertyGrid 中單擊它時,Items Collection Editor
彈出ToolStrip
的項目,因此可以進行處理。
那么我該怎么做呢?
您可以通過公開ToolStrip
本身來做到這一點,但這不是一個好主意。 UserControl
不應公開其內部控件。
如果您的用戶控件只有一個ToolStrip
您應該考慮使用CustomControl
,它是一個繼承ToolStrip
的類,您可以免費獲得其所有功能,包括設計功能。
我一直在研究這個問題一段時間,我得到的兩個最廣泛的想法是: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 的項目。 它僅在用戶明確處理項目時而不是在復制粘貼期間序列化內容。 任何關於如何處理它的想法都受到高度贊賞。
感謝所有海報。 雖然我應用了我自己的概念,但你的想法為我鋪平了道路。
我有一個解決方案,但對於 c#
[Editor("System.ComponentModel.Design.CollectionEditor, System.Design", typeof(UITypeEditor))]
[MergableProperty(false)]
[Category("Data")]
[DescriptionAttribute("ToolStripItems")]
public virtual ToolStripItemCollection ToolstripItems
{
get => toolStrip.Items;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.