在Windows开发人员设计用户界面的方式上,WPF布局模型是一个重大改进。在WPF问世之前,Windows开发人员使用刻板的基于坐标的布局将控件放到正确位置。在WPF中,这种方式虽然可行,但已经极少使用。大多数应用程序将使用类似Web的流(flow)布局;在使用流布局模型时,控件可以扩大,并将其他控件挤到其他位置。开发人员能创建与现实分辨率和窗口大小无关的、在不同的显示器上正确缩放的用户界面;当窗口内容发生变化时,界面可调整自身,并且可以自如地处理语言的切换。要利用该系统的优势,首先需要进一步理解WPF布局模型的基本概念和假设。
一、 WPF布局原则
WPF窗口只能包含单个元素。为在WPF窗口中放置多个元素并创建更贴近实用的用户界面,需要在窗口上放置一个容器,然后再这个容器中添加其他元素。
在WPF中,布局由您实用的容器来确定。尽管有多个容器可供选择,但“理想的”WPF窗口需要遵循以下几条重要原则:
- 不应显示设定元素(如控件)的尺寸。元素应当可以改变尺寸以适合它们的内容。例如,当添加更多的文本时按钮应当能够扩展。可通过设置最大和最小尺寸来限制可以接受的控件尺寸范围。
- 不应使用屏幕坐标指定元素的位置。元素应当由它们的容器根据它们的尺寸、顺序以及(可选的)其他特定与具体布局容器的信息进行排列。如果需要在元素之间添加空白空间,可使用Margin属性。
- 布局容器的子元素“共享”可用的空间。如果空间允许,布局容器会根据每个元素的内容尽可能为元素设置更合理得尺寸。它们还会向一个或多个子元素分配多余的空间。
- 可嵌套的布局容器。典型的用户界面使用Grid面板作为开始,Grid面板是WPF中功能最强大的容器,Grid面板可包含其他布局容器,包含的这些容器以最小的分组排列元素,比如带有标题的文本框、列表框中的项、工具栏上的图标以及一列按钮等。
尽管对于这几条原则而言也有一些例外,但它们反映了WPF的总体设计目标。换句话说,如果创建WPF应用程序时,循环了这些原则,将会创建出更好的、更灵活的用户界面。如果不遵循这些原则,最终将得到不是很适合WPF的并且难以维护的用户界面。
二、布局过程
WPF布局包括两个阶段:测量(measure)阶段和排列(arrange)阶段。在测量阶段,容器遍历所有子元素,并询问子元素它们所期望的尺寸。在排列阶段,容器在合适的位置放置子元素。
当然,元素未必总能等到最合适的尺寸——有事容器没有足够大的空间以适应所含的元素。在这种情况下,容器为了适应可视化区域的尺寸,就必须剪裁不能满足要求的元素。在后面可以看到,通常可通过设置最小窗口尺寸来避免这种情况。
三、布局容器
所有WPF布局容器都是派生自System.Windows.Controls.Panel抽象类的面板。如下图所示:
Panel类添加了少量成员,包括三个公有属性,如下表所示:
表 Panel的公有属性
就Panel基类本身而言没有什么特别的,但他是其它更多特殊类的起点。WPF提供了大量可用于安排布局的继承自Panel的类。下表列出了其中几个最基本的类。与所有WPF控件和大多数可视化元素一样,这些类位于System.Windows.Controls名称空间里。
表 核心布局面板
除这些核心容器外,还有几个更专业的面板,在各种控件中都可能遇到它们。这些容器包括专门用于包含特定控件子元素的面板——如TabPanel面板(在TabPanel面板中包含多个选项卡)、ToolbarPanel面板(工具栏中的多个按钮)以及ToolbarOverflowPanel面板(Toolbar控件的溢出菜单中的多个命令)。还有VirtualizingStackPanel面板,数据绑定列表空间使用该面板以大幅降低开销;还有InkCanvas控件,该控件和Canvas控件类似,但该控件支持处理平板电脑(TabletPC)上的手写笔(stylus)输入(例如,根据选择的模式,InkCanvas控件,尽管这有点违反直觉)。接下来文章会分别介绍核心容器信息。