大家一定对Visual Studio系列的Docking印象深刻, 如果你也用过SharpDevelop, 肯定也会对里面的Docking感兴趣, 更让人激动的是, 这个DockPanelSuit居然是国内高手的作品.
是的, 他叫WeifenLuo, 今天这里要介绍的就是他的大作WinFormsUI.Docking, DockPanel Suit For .NET2.0, 目前Version是2.3.1.0, 可以从这里得到最新版本的源代码
先来说说大概的架构.
这个DockPanel Suit主要有五大元素:
- DockPanel
- DockWindow
- DockPane
- DockContent
- FloatWindow
- DockPanel
这个可以说是Docking的源头, 继承自System.Windows.Forms.Panel, 其他的所有控件都由它来管理, 无论是显示, 隐藏还是DragDrop. 由它自带的DockSample可以看出, 实现的时候, 只需把该DockPanel填充整个MainForm就行, 其他所有继承自DockContent的Form只要调用Show(DockPanel)这个函数, DockPanel会自动管理这个附加到上面的窗体
- DockWindow
事实上, 对于DockPanelSuit来说, DockPanel并不是唯一的一个附加到MainForm上的Panel, DockWindow也是. DockWindow是相对于DockPanel来说较小的一个单元, 为什么在用了DockPanel之后还需要额外增加DockWindow呢? 原因很简单, DockWindow是用来划分DockPanel用的! 所以, 到目前为止, 你的MainForm上的架构应该是这样, 在一个DockPanel上面还有几个DockWindow把DockPanel分成了几块. 默认DockPanel用DockWindow创建了五个区域, 分别是DockTop, DockBottom, DockLeft, DockRight和Document, 任何一个DockPane(下面会提到)都棣属于这五个区域中的某一个. DockPanel就是通过DockWindow来管理DockPane的所在位置的. DockWindow也是继承自System.Windows.Forms.Panel
- DockPane
DockPane又是一个相对于DockWindow来势较小的一个单元, 它是DockPanelSuit的一个基本显示单元, 最终用户看到的UI都是由DockPane组合而来的. 一个DockPane基本包括一个CaptionPane, 一个DockPaneStrip, 一个Splitter以及相应的DockContents. DockPane也可以嵌套自己, 但最多只能嵌套一个, 所以, DockPane也只有一个Splitter用来自由拖动变换DockPanes的大小. CaptionPane以及DockPaneStrip都是自定义的控件, 都继承自System.Windows.Forms.Control. CaptionPane是DockPane的标题栏, 而DockPaneStrip则是DockPane的标签栏. DockContent是每个DockPane的主要显示内容. DockPane自己维护所有的CaptionPane, DockPaneStrip, Splitter和DockContents, 并指定各自的Bounds来组合一个完整的UI
- DockContent
DockContent是DockPanelSuit的基本内容单元, 而事实上, 它是一个Form. 对于所有需要Docking的窗体来说, 都要继承这个DockContent. 刚开始, DockContent并没有附加到相应的DockPane上面, 而是通过指定DockContent的Parent为相应的DockPane时才添加上去的, 并且DockPane会在OnLayout事件中计算好CaptionPane, DockPaneStrip, Splitter以及DockContent的各自位置以其组合出一个完整的UI. 值得注意的是, 在指定DockContent的Parent为DockPane之前, 需要把DockContent的TopLevel设为False, 否则会报错说"无法添加顶级控制"之类的Exception.
- FloatWindow
事实上, FloatWindow跟DockPane是同等的, 只不过DockPane是附在DockWindow上, 而FloatWindow是一个浮动窗口而已. 显然, FloatWindow是一个Form, DockPanel管理着FloatWindow跟DockPane之间的转换, 而这个转换过程也无非就是把DockContent从FloatWindow转到DockPane上, 或者把DockContent从DockPane转到FloatWindow上, 然后显示出来