65.9K
CodeProject 正在变化。 阅读更多。
Home

MultisplitContainer - 提供可调整大小内容的 FlowlayoutPanel

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (8投票s)

2009年10月19日

CPOL

5分钟阅读

viewsIcon

63724

downloadIcon

1981

提供可调整大小内容的 FlowlayoutPanel

引言

有时,您需要显示许多控件,例如编辑具有许多字段的 DataRecord。并且您希望用户能够调整这些编辑控件的大小,具体取决于显示的内容多还是少。
您可以使用 SplitContainer 来实现这一点,但 SplitContainer 只能调整两个控件的大小。要使许多编辑控件可调整大小,您可以使用许多 SplitContainer,并将它们嵌套在一起。但这会导致控件结构复杂,尤其是在 GUI 设计中进行更改时会变得困难。

MultiSplitContainer

您可以将所有编辑控件放入其中,并且每个控件都可以调整大小。当然,您可以禁用某些控件的大小调整功能,例如标签、DateTimePicker 等。
SingleColumnOrRow 模式下,Multisplitter 会布局所有编辑控件,例如 Dockstyle.Top/Bottom,除了(可选的)一个具有 Dockstyle.Fill 的控件。这是一种类似于 SplitContainer 的行为,但具有更多面板。

另一种模式

SingleColumnOrRow 模式关闭时,Multisplitter 的行为就像一个具有可调整大小的编辑控件的 FlowLayoutPanel
Multisplitter 仅支持 TopDown LeftToRight 的 FlowDirection(不支持 BottomUp/RightToLeft)。
TopDown 模式下,您还可以调整“扩展”的大小,也就是说:所有编辑控件的宽度。这对于垂直排列的控件来说,就像一种列宽。
(嗯。不容易解释,但实际使用起来很简单,请尝试一下。) 

关注点

分隔条

没有分隔条。布局尊重编辑控件的 Margin 属性,在两个控件之间的空间中,MouseMove 事件会到达 MulitSplitContainer。此时,它会检测附近的编辑控件,并将其光标设置为 HSplit(垂直尺寸调整)或 VSplit(水平尺寸调整)。

重写的 OnLayout 方法

MultisplitContainer 继承自 FlowlayoutPanel。在 SingleColumnOrRow 模式下,它会修改编辑控件的宽度/高度,以创建类似停靠的布局。在 SingleColumnOrRow.Off 模式下,布局完全由基类完成。

IExtenderProvider 属性“IsFilling”

FlowlayoutPanel 已经实现了 IExtenderProvider 接口,该接口允许为其包含的控件添加虚拟“属性”。尽管这些属性是在 MulitsplitContainer 中实现的,但它们会作为包含控件的属性显示在设计器中。
我隐藏了已弃用的“FlowBreak”扩展属性,并添加了一个“IsFilling”属性,以便用户可以将其中一个编辑控件设置为填充控件。
现在,当用户调整控件大小时,填充控件会缩小,反之亦然。(类似于 SplitContainer 的行为:左面板变大 - 右面板缩小)。

所有者绘制

因此,始终是两个面板在变化。在 SplitContainer 中,哪个是哪个显而易见,但在 Multisplitcontainer 中有许多“SplitterPanel”时,用户无法直接看到当他放大一个控件时,哪个是另一个会缩小的控件。所以我实现了一个小小的所有者绘制来在调整大小时标记这两个控件。 

IExtenderProvider 属性“SizeDynamic”

通过将控件的 Minimum/Maximum Sizes 设置为当前大小的值,可以轻松禁用大小调整。由于这在设计器中输入很不方便,所以我向控件添加了“SizeDynamic”扩展属性,该属性会设置这些值。

无停靠

由于编辑控件实际上没有被停靠,您可以轻松地将它们拖入(或拖出)其他面板。在实际的停靠场景中,您必须先取消停靠它们才能这样做。

Using the Code

编译项目并在窗体上拖放一个 MultisplitContainer。将一些编辑控件拖放到其中,例如文本框(多行开或关)、组合框、标签(自动大小开或关)。

在设计器中调整编辑控件的属性:MarginIsFillingSizeDynamic
在设计器中调整 MultisplitContainer 的属性:TopDownExpansionSingleColumnOrRowAutoScrollAutoSizeDock

运行项目并测试调整大小的行为。

看看

嗯,我必须承认:示例应用程序不是真正美观。

MultisplitContainer.gif

但它展示了一些功能

顶部的面板具有 FlowDirection.LeftToRight (MultisplitContainer.TopDown=False),这对于显示单行控件很有用,例如 Multiline.Off 的文本框、ComboboxDateTimePickerMultisplitter docked.Top 并带有 AutoSize.True。控件自动布局为 3 行,当窗体的宽度增大时,MultisplitContainer 会缩小其高度,以便 2 行控件就足够了。标准的 FlowlayoutPanel 行为。
但是 MultisplitContainer 允许用户调整文本框的大小,并且流布局会跟随。

左下角是 MultisplitContainer.TopDown=True。在此模式下,您还可以显示多行控件,并在垂直方向上调整它们的大小。您还可以调整它们的水平大小,但如果这样做,每个控件都会变大/缩小 - 这是一种带有垂直流布局的列宽。我称之为“Expansion”属性,因为当 TopDown=False 时,它也起相应作用。

右侧是 MultisplitContainer.SingleColumnOrRow 设置为 True。并且设置了一个编辑控件为“FillingControl”。
现在它的行为非常类似于 SplitContainer。所有空间都被填充,并且如果您调整一个控件的大小,FillingControl 将会补偿增长/收缩,以便所有控件都能在不使用滚动条的情况下显示。

这是第四种选择:如果没有设置 FillingControl,控件可以比 MultisplitContainer 大,并且会出现垂直滚动条。

仍有待完成

正如您所见,几乎每个编辑控件都需要一个标题标签才能有意义。在示例应用程序中,我通过将标题标签和编辑控件放在一个小面板上来自我帮助,标签停靠在左侧,编辑控件停靠填充。这仍然有点麻烦。应该创建一个“CaptionPanel”,它提供一个标题,可以接受一个编辑控件,并且会自动将编辑控件布局在剩余空间的中心。
但这可能是另一篇文章的内容了。

该控件尚未完美编程(它是新的!)。也许一些功能可以更方便地实现(例如,只能通过手动设置 MaximumSize 来锁定两个方向的大小调整)。但我希望它能为您提供一些关于实现动态布局的想法,并展示一些技术(如 IExtenderProvider 属性、用户定义的布局、所有者绘制)来使其更好或创建自己的 MultisplitContainer

而且我认为它相当稳定,因为我没有深入研究控件的行为 - 大部分工作是由老牌的 FlowlayoutPanel 完成的。

© . All rights reserved.