Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / operating-systems / Windows

Custom Controls Lesson - Using A Child Container's Control Collection

0.00/5 (No votes)
19 Feb 2013CPOL 5.3K  
I am building a custom control (an accordion style of control) for WinForms.  During the building of the collapsible panel, I ran into an issue: how do I expose the control collection of a child control as the main control's control collection?

I am building a custom control (an accordion style of control) for WinForms. During the building of the collapsible panel, I ran into an issue: how do I expose the control collection of a child control as the main control's control collection?

This may seem like a simple concept; expose a child control's Control.ControlCollection to the application. It is not as simple as it seems when you are creating child controls that are used by your custom control that are not included in the exposed Control.ControlCollection. The solution? Use the base object's Control.ControlCollection. Let's get to some code...

For this control, I want to use a header and another control to act as a container.

VB
Public Class CollapsingPanel
  Inherits Control

  Private WithEvents ctlHeader As Control
  Private WithEvents ctlClient As ScrollableControl

This is just what you would expect to expose the Control.ControlCollection.

VB
<Browsable(False), EditorBrowsable(EditorBrowsableState.Advanced)>
Public Overloads ReadOnly Property Controls As Control.ControlCollection
  Get
    Dim oControls As ControlCollection
    If IsNothing(ctlClient) Then
      oControls = Nothing
    Else
      oControls = ctlClient.Controls
    End If
    Return oControls
  End Get
End Property

This is where the unexpected happens. Ordinarily, you would use Me.Controls.Add(ctlHeader) to add controls to your custom control, but when you add the overloaded Controls property, you will get designer errors loading your control. Change the Me.Controls.Add(ctlHeader) to MyBase.Controls.Add(ctlHeader) to fix the errors.

VB
Public Sub New()
  ' This call is required by the designer.
  InitializeComponent()

  ' Add any initialization after the InitializeComponent() call.
  ctlHeader = New Control()
  With ctlHeader
    .Location = New Point(1, 1)
    .Width = MyBase.ClientSize.Width - 4
    .Height = SystemInformation.CaptionHeight

    ' Manually handle resizes
    .Anchor = AnchorStyles.None
  End With

  MyBase.Controls.Add(ctlHeader)

  ctlClient = New ScrollableControl()
  With ctlClient
    .Location = New Point(1, ctlHeader.Height + ctlHeader.Top)
    .Width = ctlHeader.Width
    .Height = MyBase.ClientSize.Height - ctlHeader.Bottom

    .AutoScroll = True

    ' Manually handle resizes
    .Anchor = AnchorStyles.None
  End With

  MyBase.Controls.Add(ctlClient)

  Me._Collapsed = False
  Me._BorderStyle = Windows.Forms.BorderStyle.FixedSingle

  Dim oButton As New System.Windows.Forms.Button()
  Me._ExpandedHeight = oButton.Height * 3
  MyBase.Size = New Size(oButton.Width, oButton.Height * 3)
End Sub

This is the first of what I hope will be several installments about custom control development.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)