Introduction
Sometimes, more or less often, you need to display many controls, e.g. to edit DataRecord
s with many fields. And you want to give the user the opportunity to resize those editing-controls, depending on whether there is much content to display or little.
You can use SplitContainer
to implement that, but SplitContainer
only makes two controls sizeable. To get many editing-controls sizeable, you may use many SplitContainer
s, and nest them into each other. But that leads to a complex structure of controls, and especially changes in GUI-Design can become difficult.
The MultiSplitContainer
You can put all editing-controls into, and each will be sizeable. Of course, you can disable sizeability for some controls, e.g. labels, DateTimePicker
s and stuff.
In SingleColumnOrRow
-Mode Multisplitter
layouts, all editing-controls like Dockstyle.Top
/Bottom
, except (optional) one control with Dockstyle.Fill
. This is a behaviour similar to a SplitContainer
, but with more Panels.
Another Mode
When SingleColumnOrRow
-Mode is off, Multisplitter
behaves as a FlowLayoutPanel
with sizeable editing-controls.
Multisplitter
only supports FlowDirection TopDown
or LeftToRight
(no BottomUp
/RightToLeft
).
In TopDown
-mode, you additionally can resize the "Expansion", that means: the width of all editing-controls. This comes up as a kind of column-width for the vertical arranged controls.
(Hmm. Not easy to explain, but in action it's easy to use, please try it out.)
Points of Interest
Splitbars
There is none. The Layout respects the Margin-Property of the editing-controls, and in the space between two controls, the MouseMove
-Event reaches the MulitSplitContainer
. At that point, it detects the nearby editing-controls, and sets its cursor to HSplit
(vertical sizement) or VSplit
(horizontal sizement).
Overridden OnLayout-Method
MultisplitContainer
inherits from FlowlayoutPanel
. In SingleColumnOrRow
-Mode it modifies the widths/heights of the editing-controls, to create a docking-like layout. With SingleColumnOrRow.Off
the Layout is completely done by the base-class.
IExtenderProvider-Property "IsFilling"
FlowlayoutPanel
already implements the IExtenderProvider
-Interface, which gives the power to add virtual "Properties" to its contained controls. Although those Properties are implemented in the MulitsplitContainer
, they are displayed in Designer as Properties of the contained controls.
I hid the overcome "FlowBreak
"-Extender-Property and added an "IsFilling
"-Property, so the user can set one of the editing-controls as Filling-Control.
Now, when the user sizes up a control, the Filling-Control shrinks and vice-versa. (like SplitContainer
-Behaviour: left panel grows - right panel shrinks).
Ownerdrawing
Thus always two Panels are changing. In SplitContainer
it's self-evident, which, but with many "SplitterPanel
s" in Multisplitcontainer
the user cannot see directly, which is the other Panel that will shrink when he enlarges one. So I implemented a little Ownerdrawing to markup the two controls while resizing.
IExtenderProvider-Property "SizeDynamic"
Disabling sizeability is simply done by setting the controls Minimum/Maximum-Sizes to the value of the current size. Since that's not very comfortable to input in Designer, I added the Extender-Property "SizeDynamic
" to the controls, which sets those Values.
No Docking
Since the editing-controls are not really docked, you can drag them easily to (or from) other panels. In a real docking-scenario, you must undock them before you can do so.
Using the Code
Compile project and drag a MultisplitContainer
on Form. Drag some editing-controls on it, Textboxes (MultiLine on or off), Comboboxes, Labels (Autosize on or off).
Play in Designer with editing-control-Properties: Margin
, IsFilling
, SizeDynamic
play in Designer with MultisplitContainer
-Properties: TopDown
, Expansion
, SingleColumnOrRow
, AutoScroll
, AutoSize
, Dock
.
Run project and test the resizing-behaviour.
Take a Look
Ãhm, I must admit: The sample-app isn't a real beauty.
But it shows some features:
The Panel on Top has FlowDirection.LeftToRight (MultisplitContainer.TopDown=False)
, which is useful to display one-line-controls, like Textboxes with Multiline.Off
, Combobox
es, DateTimePicker
s. The Multisplitter
is docked.Top
with AutoSize.True
. The controls are automatically layouted in 3 lines, and the MultisplitContainer
will shrink its Height when the form enlarges its width, so that 2 lines of controls are sufficient. Usual FlowlayoutPanel
-behaviour.
But MultisplitContainer
allows the user to resize the textboxes, and the flowlayout will follow.
Below on the left, there is MultisplitContainer.TopDown=True
. In this mode, you can also display multi-line-controls, and resize them in vertical direction. You can also size them in horizontal direction, but if you do so, every control grows/shrinks - that is a kind of column-with the vertical Flow-Layout. I called that Property "Expansion", because when TopDown=False
it works accordingly.
On the right, there is MultisplitContainer.SingleColumnOrRow
set to True
. And there is set one editing-control as "FillingControl
".
Now it behaves very similar to SplitContainer
. All Space is filled, and if you resize a control, the FillingControl
will compensate the growing/shrinking, so that all controls stay in view without using scrollbars.
That's the fourth opportunity: If no FillingControl
is set, the controls can grow greater than the MultisplitContainer
, and the vertical scrollbar will appear.
Still Something To Do
As you see, nearly every editing-control needs a Caption-Label to make sense. In the Sample-App, I helped myself by placing Caption-Label and editing-control together on a little panel, the label docked left, the editing-control docked fill. That still is a little circumstantial to figure out. One should create a "CaptionPanel
", which would provide a caption and can take an editing-control, and it would layout the editing-control automatically centered in the remaining space.
But that may be stuff for another article.
The control is not programmed out perfectly (it's new!). Maybe some features could be implemented more comfortably (e.g. locking sizeability in both directions only can be done by setting MaximumSize
by hand). But I hope that it gives you some ideas to implement dynamic layout, and it shows some techniques (as IExtenderProvider
-Properties, userdefined Layout, Ownerdrawing) to make it better or to create an own MultisplitContainer
.
And I think, it's quite stable, because I didn't grasp very deep into the controls' behaviour - most of the work is done by the good old FlowlayoutPanel
.