I'm trying to create a control with a parent control designer behavior, but unlike a regular parent control, I need a control inside of it to be the one that controls are put on. It needs to be similar to the tabcontrol, where controls can be placed on the individual tab pages, but not on other areas of the control, such as the tabs themselves. Does anyone know how to do this?
There's a basic example here: http://www.vbdotnetforums.com/component-development/25052-creating-control-panel.html
In addition override CanParent in control designer, where you return True when a control can be added. In example linked if I wanted only to allow controls to be added to the Panel I would check 'If TypeOf Me.Control Is Panel'. Me.Control in control designer refers to the control the designer is currently designing.
I have another question though. With this method, the user is allowed to make changes to the panel such as properties and resizing. Is it possible to disallow this?
You probable have to inherit the panel control, shadow Location/Size properties and apply Browsable attribute and other behaviours, and apply a separate designer where you override SelectionRules.
Here is a more extended example, a UserControl (RestrictArea) containing a GroupBox (Box), controls can only be added to the box container. Both classes has their own designer.
RestrictArea:
The user control exposes the Box as a property, DesignerSerializationVisibility (Content) attribute is added so that code is generated for adding controls to it.
Imports System.ComponentModel
<Designer(GetType(RestrictAreaDesigner))> _
Public Class RestrictArea '(inherits UserControl)
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public ReadOnly Property Box() As Box
Get
Return Me.Box1
End Get
End Property
End Class
Box:
Box class hides a few properties, expand as needed and/or add custom behaviour. DesignerSerializationVisibility is not hidden for Location and Size since code for these need to be serialized, if not they would reset to default each rebuild. While properties can be hidden by overriding PreFilterProperties in control designer, this will only hide the property from designer, so they will still be available in code. Therefore it is best to Shadow the property as shown in Box class to hide properties that should not be available.
Notice the ToolboxItem attribute on Box class, I added that after adding a box to the user control from ToolBox, much more convenient to design the user control and adding the attribute hides it from ToolBox after that.
Imports System.ComponentModel
<Designer(GetType(BoxDesigner)), ToolboxItem(False)> _
Public Class Box
Inherits GroupBox
<EditorBrowsable(EditorBrowsableState.Never), Browsable(False)> _
Public Shadows Property Location As Point
Get
Return MyBase.Location
End Get
Set(value As Point)
MyBase.Location = value
End Set
End Property
<EditorBrowsable(EditorBrowsableState.Never), Browsable(False)> _
Public Shadows Property Size As Size
Get
Return MyBase.Size
End Get
Set(value As Size)
MyBase.Size = value
End Set
End Property
<EditorBrowsable(EditorBrowsableState.Never), Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Shadows Property Dock As DockStyle
Get
Return MyBase.Dock
End Get
Set(value As DockStyle)
MyBase.Dock = value
End Set
End Property
End Class
Here are their designers, requires reference to System.Design assembly.
RestrictAreaDesigner:
Inherits ParentControlDesigner because CanParent need to be used. CanParent returns False, no controls can be added directly to the user control. This has no effect when designing the user control itself, only when designing an instance of it on a form.
About the Initialize method. The code in previous example using Container.Add will make the added component standalone (ex "Box"), while using EnableDesignMode method adds the control as a child control (ex "RestrictArea.Box"). Latter makes sense here having a fixed sub-area within the user control. Designers for child controls added by EnableDesignMode is exposed by NumberOfInternalControlDesigners and InternalControlDesigner function overrides as shown. This difference can also be seen with TabControl/TabPage (separate pages) and SplitContainer/SplitterPanel (fixed child panels).
Imports System.Windows.Forms.Design
Imports System.ComponentModel.Design
Public Class RestrictAreaDesigner
Inherits ParentControlDesigner
Private boxdesigner As ScrollableControlDesigner
Public Overrides Sub Initialize(ByVal component As System.ComponentModel.IComponent)
MyBase.Initialize(component)
Dim area As RestrictArea = DirectCast(component, RestrictArea)
EnableDesignMode(area.Box, "Box")
Dim host As IDesignerHost = DirectCast(GetService(GetType(IDesignerHost)), IDesignerHost)
Me.boxdesigner = host.GetDesigner(area.Box)
End Sub
Public Overrides Function CanParent(control As System.Windows.Forms.Control) As Boolean
Return False
End Function
Public Overrides Function NumberOfInternalControlDesigners() As Integer
Return 1
End Function
Public Overrides Function InternalControlDesigner(internalControlIndex As Integer) As System.Windows.Forms.Design.ControlDesigner
Return Me.boxdesigner
End Function
End Class
BoxDesigner:
Inherits ScrollableControlDesigner, which is derived from ParentControlDesigner, add support for AutoScroll container.
CanParent need not overriding here, default allows all parenting.
CanBeParentedTo, similar to TabPage the Box should only be parented to RestrictArea user control.
SelectionRules, the box is locked in designer, can't be moved or resized.
Imports System.Windows.Forms.Design
Imports System.ComponentModel.Design
Public Class BoxDesigner
Inherits ScrollableControlDesigner
Public Overrides ReadOnly Property SelectionRules As System.Windows.Forms.Design.SelectionRules
Get
Return SelectionRules.Locked
End Get
End Property
Public Overrides Function CanBeParentedTo(parentDesigner As System.ComponentModel.Design.IDesigner) As Boolean
Return TypeOf parentDesigner.Component Is RestrictArea
End Function
End Class
As always, study the documentation for the involved classes, also studying existing classes using .Net Reflector can be useful, for example the mentioned TabControl/TabPage and SplitContainer/SplitterPanel their designers.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.