Sometimes, more or less often, you need to display many controls, e.g. to edit
DataRecords 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
SplitContainers, and nest them into each other. But that leads to a complex structure of controls, and especially changes in GUI-Design can become difficult.
You can put all editing-controls into, and each will be sizeable. Of course, you can disable sizeability for some controls, e.g. labels,
DateTimePickers and stuff.
Multisplitter layouts, all editing-controls like
Bottom, except (optional) one control with
Dockstyle.Fill. This is a behaviour similar to a
SplitContainer, but with more Panels.
SingleColumnOrRow-Mode is off,
Multisplitter behaves as a
FlowLayoutPanel with sizeable editing-controls.
Multisplitter only supports FlowDirection
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
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).
MultisplitContainer inherits from
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.
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).
Thus always two Panels are changing. In
SplitContainer it's self-evident, which, but with many "
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.
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.
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:
play in Designer with
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
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
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 "
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
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