473,322 Members | 1,379 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

How to use an Items Collection Editor on a custom UserControl (.Net 4, Winforms)?

88 64KB
I created a UserControl that contains a custom ToolStrip Control. While using the UserControl throughout an application, the ToolStrip control cannot be accessed directly, as logically it's embedded in the UserControl. So, to access the items of the ToolStrip I defined a readonly property in the UserControl class that returns the items of the ToolStrip. Now programmatically the items of the ToolStrip can be edited by using the UserControl.Items property, but I cannot do the same in the design mode. Like someone drags the UserControl from the ToolBox to the form, goes to the property grid, chooses the Items property and manipulates the items of the ingrained ToolStrip accordingly; just as we do with any standard ToolStrip control's items collection with the help of Items Collection Editor. Herein, though the Items property of the UserControl shows in the property grid, it's not usable and every time I click, it shows an error message- 'Value cannot be null. Parameter name: value'. I'm sure this is because the property is declared just as readonly and I need to hike more so that when it is clicked in the property grid, the Items Collection Editor pops up with the items of the ToolStrip and can be handled consequently. So how should I be doing this?
Please state if I'm not clear.

Regards!
Aug 23 '12 #1
1 4497
priyamtheone
88 64KB
Hi there!
I have been working on the issue for a while, and the two most widely held ideas I got are:
1) Exposing the ToolStrip as a property.
2) Use a ControlDesigner for the UserControl and set EnableDesignMode for the ToolStrip.

But somehow none of them actually served my purpose, as exposing the ToolStrip would let the user have full control on it, which was not my objective. The second option would even put the user up with deleting the ToolStrip. Hence I had to figure out a different approach. That's when I tripped upon the CollectionBase class.

As it says, the CollectionBase class is the abstract base class for a strongly typed collection. So how about maintaining the ToolStrip item collection through it?
I created an instance of the CollectionBase class and regulated the addition, modification, fetching and deletion of the ToolStrip items through it. Each item in the collection hails from a class that is inherited from the ToolStripButton class. In that way, individual item can be handled as any standard ToolStripButton and you can hide or show the properties to the user accordingly. Lastly, the ToolStrip in question is set as the parent of the CollectionBase which eventually becomes the parent of each ToolStripItem too. Here's the concept:

Expand|Select|Wrap|Line Numbers
  1. Imports System.ComponentModel
  2. Imports System.Windows.Forms
  3. Imports Office2003
  4. Imports System.Drawing
  5. Imports System.Windows.Forms.Design
  6.  
  7. Public Class MyUserControl
  8.     Private _Buttons As MyUserControlButtons
  9.     Public Event MyUserControlButtonClicked(ByVal Sender As MyUserControlButton)
  10.  
  11.     Public Sub New()
  12.         MyBase.New()
  13.  
  14.         'This call is required by the Component Designer.
  15.         InitializeComponent()
  16.  
  17.         _Buttons = New MyUserControlButtons(MyToolStrip)
  18.     End Sub
  19.  
  20.     <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
  21.     Public ReadOnly Property Buttons As MyUserControlButtons
  22.         Get
  23.             Return _Buttons
  24.         End Get
  25.     End Property
  26.  
  27.     Private Sub MyToolStrip_ItemClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ToolStripItemClickedEventArgs) Handles MyToolStrip.ItemClicked
  28.      'Check if the ToolStrip item clicked is a ToolStripButton...
  29.         If TypeOf e.ClickedItem Is ToolStripButton Then
  30.             'Insert your code here...
  31.  
  32.          'Raise the custom event.
  33.             RaiseEvent MyUserControlButtonClicked(Item)
  34.         End If
  35.     End Sub
  36. End Class
  37.  
  38. #Region "Manager classes for MyUserControl buttons."
  39.  
  40. Public Class MyUserControlButtons
  41.     Inherits CollectionBase
  42.     Private _Parent As ToolStrip
  43.  
  44.     ''' <summary>
  45.     ''' Initializes a new instance of the MyUserControlButtons class.
  46.     ''' </summary>
  47.     ''' <param name="Holder">The ToolStrip that contains the items of the MyUserControlButtons class.</param>
  48.     Public Sub New(ByVal Holder As ToolStrip)
  49.         MyBase.New()
  50.         _Parent = Holder
  51.     End Sub
  52.  
  53.     ''' <summary>
  54.     ''' The ToolStrip that contains this item.
  55.     ''' </summary>
  56.     Public ReadOnly Property Parent() As ToolStrip
  57.         Get
  58.             Return _Parent
  59.         End Get
  60.     End Property
  61.  
  62.     ''' <summary>
  63.     ''' Gets the element at the specified index.
  64.     ''' </summary>
  65.     ''' <param name="Index">The zero-based index of the element to get.</param>
  66.     Default Public ReadOnly Property Item(ByVal Index As Integer) As MyUserControlButton
  67.         Get
  68.             Return CType(List(Index), MyUserControlButton)
  69.         End Get
  70.     End Property
  71.  
  72.     ''' <summary>
  73.     ''' Adds an item to the collection.
  74.     ''' </summary>
  75.     Public Function Add() As MyUserControlButton
  76.         Return Me.Add
  77.     End Function
  78.  
  79.     ''' <summary>
  80.     ''' Adds an item to the collection.
  81.     ''' </summary>
  82.     ''' <param name="Value">The object to add to the collection.</param>
  83.     Public Sub Add(ByVal Value As MyUserControlButton)
  84.         List.Add(Value)
  85.         Value.Parent = Me.Parent
  86.     End Sub
  87.  
  88.     ''' <summary>
  89.     ''' Adds an item to the collection.
  90.     ''' </summary>
  91.     ''' <param name="Name">The name of the object to add to the collection.</param>
  92.     ''' <param name="Image">The image of the object to add to the collection.</param>
  93.     Public Function Add(ByVal Name As String, ByVal Image As Image) As MyUserControlButton
  94.         Dim b As MyUserControlButton = New MyUserControlButton(Me.Parent)
  95.         b.Name = Name
  96.         b.Text = Name
  97.         b.Image = Image
  98.         Me.Add(b)
  99.         Return b
  100.     End Function
  101.  
  102.     ''' <summary>
  103.     ''' Adds an item to the collection.
  104.     ''' </summary>
  105.     ''' <param name="Name">The name of the object to add to the collection.</param>
  106.     ''' <param name="Text">The text of the object to add to the collection.</param>
  107.     ''' <param name="Image">The image of the object to add to the collection.</param>
  108.     Public Function Add(ByVal Name As String, ByVal Text As String, ByVal Image As Image) As MyUserControlButton
  109.         Dim b As MyUserControlButton = New MyUserControlButton(Me.Parent)
  110.         b.Name = Name
  111.         b.Text = Text
  112.         b.Image = Image
  113.         Me.Add(b)
  114.         Return b
  115.     End Function
  116.  
  117.     ''' <summary>
  118.     ''' Removes the first occurence of a specific object from the collection.
  119.     ''' </summary>
  120.     ''' <param name="Value">The object to be removed.</param>
  121.     Public Sub Remove(ByVal Value As MyUserControlButton)
  122.         List.Remove(Value)
  123.     End Sub
  124.  
  125.     ''' <summary>
  126.     ''' Determines the index of a specific item in the collection.
  127.     ''' </summary>
  128.     ''' <param name="Value">The object to locate in the collection.</param>
  129.     Public Function IndexOf(ByVal Value As Object) As Integer
  130.         Return List.IndexOf(Value)
  131.     End Function
  132.  
  133.     ''' <summary>
  134.     ''' Determines whether the collection contains a specific value.
  135.     ''' </summary>
  136.     ''' <param name="Value">The object to locate in the collection.</param>
  137.     Public Function Contains(ByVal Value As MyUserControlButton) As Boolean
  138.         Return List.Contains(Value)
  139.     End Function
  140.  
  141.     Protected Overrides Sub OnInsertComplete(ByVal index As Integer, ByVal value As Object)
  142.         Dim b As MyUserControlButton = CType(value, MyUserControlButton)
  143.         b.Parent = Me.Parent
  144.         Me.Parent.Items.Insert(index, CType(value, ToolStripButton))
  145.         MyBase.OnInsertComplete(index, value)
  146.     End Sub
  147.  
  148.     Protected Overrides Sub OnSetComplete(ByVal index As Integer, ByVal oldValue As Object, ByVal newValue As Object)
  149.         Dim b As MyUserControlButton = CType(newValue, MyUserControlButton)
  150.         b.Parent = Me.Parent
  151.         MyBase.OnSetComplete(index, oldValue, newValue)
  152.     End Sub
  153.  
  154.     Protected Overrides Sub OnClearComplete()
  155.         MyBase.OnClearComplete()
  156.     End Sub
  157. End Class
  158.  
  159. Public Class MyUserControlButton
  160.     Inherits ToolStripButton
  161.  
  162.     ''' <summary>
  163.     ''' Initializes a new instance of the MyUserControlButton class.
  164.     ''' </summary>
  165.     Sub New()
  166.         MyBase.New()
  167.         Init()
  168.     End Sub
  169.  
  170.     ''' <summary>
  171.     ''' Initializes a new instance of the MyUserControlButton class.
  172.     ''' </summary>
  173.     ''' <param name="Holder">The ToolStrip that contains the StackView button.</param>
  174.     Sub New(ByVal Holder As ToolStrip)
  175.         MyBase.New()
  176.         Init()
  177.         Me.Parent = Holder
  178.     End Sub
  179.  
  180.     Private Sub Init()
  181.         Me.AutoToolTip = False
  182.         Me.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText
  183.         Me.ImageAlign = ContentAlignment.MiddleLeft
  184.         Me.ImageIndex = -1
  185.         Me.ImageKey = ""
  186.         Me.ImageTransparentColor = Color.Magenta
  187.         Me.TextAlign = ContentAlignment.MiddleLeft
  188.         Me.TextDirection = ToolStripTextDirection.Horizontal
  189.     End Sub
  190.  
  191.     ''' <remarks>
  192.     ''' Hide this property from the user in both design and code editor.
  193.     ''' </remarks>
  194.     <Browsable(False),
  195.     EditorBrowsable(False)> _
  196.     Public Shadows Property AccessibleDefaultActionDescription As String
  197.         Get
  198.             Return MyBase.AccessibleDefaultActionDescription
  199.         End Get
  200.         Set(ByVal value As String)
  201.             MyBase.AccessibleDefaultActionDescription = value
  202.         End Set
  203.     End Property
  204.  
  205.     ''' <remarks>
  206.     ''' Hide this property from the user in both design and code editor.
  207.     ''' </remarks>
  208.     <Browsable(False),
  209.     EditorBrowsable(False)> _
  210.     Public Shadows Property AccessibleDescription As String
  211.         Get
  212.             Return MyBase.AccessibleDescription
  213.         End Get
  214.         Set(ByVal value As String)
  215.             MyBase.AccessibleDescription = value
  216.         End Set
  217.     End Property
  218.  
  219.     ''' <remarks>
  220.     ''' Hide this property from the user in both design and code editor.
  221.     ''' </remarks>
  222.     <Browsable(False),
  223.     EditorBrowsable(False)> _
  224.     Public Shadows Property AccessibleName As String
  225.         Get
  226.             Return MyBase.AccessibleName
  227.         End Get
  228.         Set(ByVal value As String)
  229.             MyBase.AccessibleName = value
  230.         End Set
  231.     End Property
  232.  
  233.  
  234.     ' Keep on hiding the irrelevant properties...
  235.  
  236.  
  237.     ''' <summary>
  238.     ''' Gets or sets a value indicating whether default or custom ToolTip text is displayed on the ToolStripButton.
  239.     ''' </summary>
  240.     <DefaultValue(False)> _
  241.     Public Shadows Property AutoToolTip As Boolean
  242.         Get
  243.             Return MyBase.AutoToolTip
  244.         End Get
  245.         Set(ByVal value As Boolean)
  246.             MyBase.AutoToolTip = value
  247.         End Set
  248.     End Property
  249.  
  250.     ''' <summary>
  251.     ''' Specifies whether the image and text are rendered.
  252.     ''' </summary>
  253.     <DefaultValue(GetType(ToolStripItemDisplayStyle), "ImageAndText")> _
  254.     Public Overrides Property DisplayStyle As System.Windows.Forms.ToolStripItemDisplayStyle
  255.         Get
  256.             Return MyBase.DisplayStyle
  257.         End Get
  258.         Set(ByVal value As System.Windows.Forms.ToolStripItemDisplayStyle)
  259.             MyBase.DisplayStyle = value
  260.         End Set
  261.     End Property
  262.  
  263.     ''' <summary>
  264.     ''' The image that will be displayed on the control.
  265.     ''' </summary>
  266.     Public Overrides Property Image() As Image
  267.         Get
  268.             Return MyBase.Image
  269.         End Get
  270.         Set(ByVal value As Image)
  271.             MyBase.Image = value
  272.         End Set
  273.     End Property
  274.  
  275.     ''' <summary>
  276.     ''' Gets or sets the alignment of the image on a ToolStripItem.
  277.     ''' </summary>
  278.     <DefaultValue(GetType(ContentAlignment), "MiddleLeft")> _
  279.     Public Shadows Property ImageAlign As ContentAlignment
  280.         Get
  281.             Return MyBase.ImageAlign
  282.         End Get
  283.         Set(ByVal value As ContentAlignment)
  284.             MyBase.ImageAlign = value
  285.         End Set
  286.     End Property
  287.  
  288.     <EditorBrowsable(False),
  289.     DefaultValue(-1)> _
  290.     Public Shadows Property ImageIndex As Integer
  291.         Get
  292.             Return MyBase.ImageIndex
  293.         End Get
  294.         Set(ByVal value As Integer)
  295.             MyBase.ImageIndex = value
  296.         End Set
  297.     End Property
  298.  
  299.     <EditorBrowsable(False),
  300.     DefaultValue("")> _
  301.     Public Shadows Property ImageKey As String
  302.         Get
  303.             Return MyBase.ImageKey
  304.         End Get
  305.         Set(ByVal value As String)
  306.             MyBase.ImageKey = value
  307.         End Set
  308.     End Property
  309.  
  310.     ''' <summary>
  311.     ''' Gets or sets the color to treat as transparent in a ToolStripItem image.
  312.     ''' </summary>
  313.     Public Shadows Property ImageTransparentColor As Color
  314.         Get
  315.             Return MyBase.ImageTransparentColor
  316.         End Get
  317.         Set(ByVal value As Color)
  318.             MyBase.ImageTransparentColor = value
  319.         End Set
  320.     End Property
  321.  
  322.     ''' <summary>
  323.     ''' Specifies the name used to identify the object.
  324.     ''' </summary>
  325.     Public Shadows Property Name() As String
  326.         Get
  327.             Return MyBase.Name
  328.         End Get
  329.         Set(ByVal value As String)
  330.             MyBase.Name = value
  331.         End Set
  332.     End Property
  333.  
  334.     ''' <summary>
  335.     ''' The ToolStrip that contains this item.
  336.     ''' </summary>
  337.     <Browsable(False)> _
  338.     Public Shadows Property Parent As ToolStrip
  339.         Get
  340.             Return MyBase.Parent
  341.         End Get
  342.         Set(ByVal value As ToolStrip)
  343.             MyBase.Parent = value
  344.         End Set
  345.     End Property
  346.  
  347.     ''' <summary>
  348.     ''' The text that will be displayed on the control.
  349.     ''' </summary>
  350.     Public Overrides Property Text() As String
  351.         Get
  352.             Return MyBase.Text
  353.         End Get
  354.         Set(ByVal value As String)
  355.             MyBase.Text = value
  356.         End Set
  357.     End Property
  358.  
  359.     ''' <summary>
  360.     ''' Gets or sets the alignment of the text on a ToolStripLabel.
  361.     ''' </summary>
  362.     <DefaultValue(GetType(ContentAlignment), "MiddleLeft")> _
  363.     Public Overrides Property TextAlign As ContentAlignment
  364.         Get
  365.             Return MyBase.TextAlign
  366.         End Get
  367.         Set(ByVal value As ContentAlignment)
  368.             MyBase.TextAlign = value
  369.         End Set
  370.     End Property
  371.  
  372.     <Browsable(False),
  373.     EditorBrowsable(False),
  374.     DefaultValue(GetType(ToolStripTextDirection), "Horizontal")> _
  375.     Public Overrides Property TextDirection As ToolStripTextDirection
  376.         Get
  377.             Return MyBase.TextDirection
  378.         End Get
  379.         Set(ByVal value As ToolStripTextDirection)
  380.             MyBase.TextDirection = value
  381.         End Set
  382.     End Property
  383.  
  384.  
  385.     ' Define other properties accordingly...
  386. End Class
  387.  
  388. #End Region
MyUserControl is the custom user control containing the ToolStrip named MyToolStrip. MyUserControlButtons is the class that inherits from CollectionBase and each item of MyUserControlButtons is an object of MyUserControlButton class that inherits from ToolStripButton.

In the constructor of MyUserControl, MyUserControlButtons is instantiated with MyToolStrip as its parent. Items are added to MyUserControlButtons by creating new objects from MyUserControlButton. Properties of the items to be hidden or shown are managed in MyUserControlButton.
MyUserControl returns the list of the buttons through the read only property 'Buttons'. Note the DesignerSerializationVisibility attribute of the 'Buttons' property. It specifies the type of persistence to use when serializing a property on a component at design time. The 'Content' enumeration member tells the code generator to produce code for the contents of the object, rather than for the object itself.

The drawback in this approach is that you cannot retain the items of the ToolStrip while performing copy-paste on the UserControl. It serializes the contents only when items are handled explicitly by the user but not during copy-paste. Any idea of how to deal with it is highly appreciated.

Thanks to all posters. Though I applied my own concept, your ideas paved my way.
Sep 15 '12 #2

Sign in to post your reply or Sign up for a free account.

Similar topics

7
by: Martin Schulze | last post by:
Hello, i tried to compose myself a custom usercontrol which is derieved from System.Windows.Forms.UserControl. It contains 2 comboboxes and one textbox (which are also custom controls, but...
8
by: Tinus | last post by:
Hello all, I've create a custom control (UserControl) and have a custom Item Collection. The control is a custom calendar which is draw using the Graphics Rectangle etc. functions. It is drawn...
2
by: Edward Diener | last post by:
In C++ an overridden virtual function in a derived class must have the exact same signature of the function which is overridden in the base class, except for the return type which may return a...
1
by: Friskusen | last post by:
I have (almost) added a simple Toolbar custom control to my control library. The Items on the toolbar are implemented in a class named ToolbarItem. I also use a class ToolbarItemCollection to...
4
by: Michael | last post by:
Dear all .. If I want to use develop a user control and declare a public property which the type is System.Windows.Forms.GridTableStylesCollection For example : Public Class LookAndView...
0
by: MajorTom | last post by:
Hello I am creating a UserControl that has a DataGridView control as a member. I want to expose the column collection of the DataGridView, as a property of my control. in my code I have:
0
by: cranley | last post by:
Hi. I'm currently building a custom control. On my custom control is a colleciton property which I wish to edit with the VS.NET collection editor. So far I have everything working as planned,...
5
by: Blue | last post by:
We have a custom word processing type editor built with C# and .NET 2.0 and we need to support typing in languages other than English. I want to be able to use the Windows IME to enter in text...
1
by: timnels | last post by:
I have a control that is subclassing a label control and I want to a a property that is a List of a custom class. The collection editor _seems_ to work fine. I can add new items to the list and it...
2
by: ME | last post by:
I have a property that is a generic list of type IAddress (List<IAddress>). When I attempt to view this property using the Property Grid control it plainly says "Collection" and offers the typical...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.