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.
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
.
<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.
Public Sub New()
InitializeComponent()
ctlHeader = New Control()
With ctlHeader
.Location = New Point(1, 1)
.Width = MyBase.ClientSize.Width - 4
.Height = SystemInformation.CaptionHeight
.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
.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.