DockPanelDesigner
The ParentControlDesigner for DockPanel — provides 10 designer verbs, auto-key generation, intelligent move snapping, and stack reordering at design time
Overview
Namespace: TheTechIdea.Beep.Winform.Controls.Design.Server.Docking.Designers
Inheritance: ParentControlDesigner (allows child controls to be dropped onto the panel)
Visibility: internal sealed
DockPanelDesigner provides the design-time experience for individual DockPanel controls. It extends ParentControlDesigner so users can drag child controls onto the panel from the toolbox. It provides 10 designer verbs for docking/manageCommands and intelligent snapping when the panel is moved on the form.
Key Features
- Auto-key generation — On InitializeNewComponent, a unique Key is derived from the component's site name (e.g., "dockPanel1")
- Intelligent move snapping — When dragged, panel snaps to nearest dock edge or stacks with overlapped panels
- Float detection — Dragging outside the host form (>40px boundary) floats the panel
- 10 designer verbs — Dock Left/Right/Top/Bottom/Fill, Stack with Prev/Next, Move Earlier/Later in Stack, Remove
- Smart-tag — DockPanelActionList with position, sizing, and behavior properties
- Resize forwarding — Panel resize delegates to BeepDockingDesignerWiring for proportional recalculation
Designer Verbs (10)
| Verb | Method | Description |
|---|---|---|
| Dock &Left | ApplyDockPosition(Left) | Move panel to left edge |
| Dock &Right | ApplyDockPosition(Right) | Move panel to right edge |
| Dock &Top | ApplyDockPosition(Top) | Move panel to top edge |
| Dock &Bottom | ApplyDockPosition(Bottom) | Move panel to bottom edge |
| Dock &Fill | ApplyDockPosition(Fill) | Expand to fill remaining space |
| Stack with Previous Panel | StackWithPreviousPanel() | Group with previous sibling as tabs |
| Stack with Next Panel | StackWithNextPanel() | Group with next sibling as tabs |
| Move Earlier in Stack | MoveEarlierInStack() | Reorder to earlier tab position |
| Move Later in Stack | MoveLaterInStack() | Reorder to later tab position |
| &Remove Panel | RemovePanel() | Permanently delete the panel |
Design-Time Behaviors
Auto-Key on InitializeNewComponent
When a new DockPanel is created (either from the manager's "Add Panel" verb or by drag-dropping), the designer auto-generates a unique Key from the designer host name:
public override void InitializeNewComponent(IDictionary defaultValues)
{
base.InitializeNewComponent(defaultValues);
string key = Component.Site?.Name ?? "dockPanel";
SetPanelProperty("Key", key);
SetPanelProperty("Title", key);
}Move Snapping
When the user drags a DockPanel in the designer, the OnDesignerComponentChanged handler detects Bounds/Location/Size changes. For move changes:
- FindPanelUnderCenter() — Checks if another panel is at the same parent level under the moved panel's center. If yes, stacks them.
- ShouldFloatPanel() — Checks if the panel center is >40px outside the host form bounds. If yes, floats the panel.
- ResolveNearestDockPosition() — Calculates the nearest dock edge (Left/Right/Top/Bottom) based on distance from center to host form bounds.
Resize Forwarding
Resize changes are forwarded to BeepDockingDesignerWiring.ResizePanel() for proportional recalculation of adjacent panels.
Selection Tracking
When a DockPanel becomes the primary selection in the designer, BeepDockingDesignerWiring.ActivateDesignPanel() is called to update the docking manager's active panel state.
DockPanelActionList Smart-Tag
| Property | Type | Description |
|---|---|---|
| Key | string | Unique panel identifier |
| Title | string | Panel display title (caption) |
| DockPosition | DockPosition | Docked edge |
| PreferredWidth | int | Preferred panel width |
| PreferredHeight | int | Preferred panel height |
| MinWidth / MinHeight | int | Minimum resize dimensions |
| CanClose / CanFloat / CanAutoHide | bool | Capability flags |
| ShowCaption | bool | Show/hide panel caption bar |
Examples
Snap-to-Edge Logic
private DockPosition ResolveNearestDockPosition()
{
var panel = (DockPanel)Component;
var hostBounds = panel.Manager?.HostForm?.Bounds
?? panel.Parent?.Bounds;
var center = new Point(
panel.Bounds.Left + panel.Bounds.Width / 2,
panel.Bounds.Top + panel.Bounds.Height / 2);
// Calculate distances to each edge
int distLeft = center.X - hostBounds.Left;
int distRight = hostBounds.Right - center.X;
int distTop = center.Y - hostBounds.Top;
int distBottom = hostBounds.Bottom - center.Y;
// Return nearest edge
int min = Math.Min(Math.Min(distLeft, distRight),
Math.Min(distTop, distBottom));
if (min == distLeft) return DockPosition.Left;
if (min == distRight) return DockPosition.Right;
if (min == distTop) return DockPosition.Top;
return DockPosition.Bottom;
}