转自:http://www.cnblogs.com/niyw/archive/2010/10/31/1863908.html
前言

前段时间忙了一阵子Google Earth,这周又忙了一阵子架构师论文开题报告,现在终于有时间继续<WPF之路>了。先回忆一下上篇的内容,在《从HelloWorld到WPF World》中,我们对WPF有了个大概的了解,并了解了初学WPF时应该从哪些知识点入手。今天我们就从最基本的知识点之一布局系统来继续学习WPF,主要包括如下内容。



0,什么是布局


  这是一个很简单的问题。简单来说,就是把一些控件有条理的摆放在界面上合适的位置,显然摆的乱七八糟不能算布局。在WPF中,这个条理与WinForm中略有不同,让我们看个很简单的界面:

这样子的界面大家在熟悉不过了。依图所示,WPF先用蓝线(假设的线)将界面划分为上下两部分,然后再有红线划分出多个方格,最后放入控件,其中每部分中的控件或划分的空格只能纵向排列,或横向排列,不能有其他选择。大多数情况下,WPF程序界面上的控件都要按照此种递归的方法逐个排列,最终形成所看到的界面。

1,基本元素——面板


  在上节中我们了解了WPF布局原理,这可以简单理解为大控件中按排或列放入小控件,小控件在按照同样规则放入更小控件。这种能放入其他控件的控件是WPF布局系统中的基本元素——面板。面板是用来放东西的,既包括控件元素,也包括面板自己。面板不仅能承载其他子元素(控件),还能控制子元素的大小,位置以及如何排列。例如上述例子中,蓝线划分的面板控制子元素只能上下排列,而红线划分的面板控制的子元素只能横向排列。

WPF默认提供了几种面板都是从基面板(Panel)继承而来,看一下它们的继承链。

System.Windows.Threading.DispatcherObject
        System.Windows.DependencyObject
          System.Windows.Media.Visual
            System.Windows.UIElement
              System.Windows.FrameworkElement

System.Windows.Controls.Control
                System.Windows.Controls.Panel
                  System.Windows.Controls.Canvas
                  System.Windows.Controls.DockPanel
                  System.Windows.Controls.Grid
                  System.Windows.Controls.StackPanel
                  System.Windows.Controls.VirtualizingPanel
                  System.Windows.Controls.WrapPanel
 

2,常用容器控件


WPF默认提供了数种布局控件,常用的包括如下几种:

名称 用法 说明
Canvas 此面板可承载任意元素,包括控件,图形,甚至文字。各种元素依据屏幕坐标确定位置。
DockPanel 此面板可指定元素的排列停靠方式,每个子元素的排列方式可以不同。
Grid 此面板使子元素按照纵横网格排列。
StackPanel 此面板使子元素按照水平或垂直方向排列,两个方向只能选其一。

VirtualizingStackPanel

与StackPanel相同,不同之处在于它可以使内容虚拟化。
WrapPanel 使子元素按照水平或垂直方向排列,在行或列处换行或列,依旧按照水平或垂直方向从左到右或从上到下排列。

 

3,测量与排列


  当我们在面板上放入子元素,并设置相应的属性时,WPF的布局系统自动为我们完成2个过程:测量和排列,这是两个非常重要的过程。

  由于WPF界面元素有很多与布局有关的属性,如坐标,大小,对齐方式,相对位置,间距等。首先这些属性使用的是与设备无关的分辨率单元,这导致同样大小的元素在不同界面上显示的效果可能不同;其次每个属性值有一定的优先级,例如Button的Height和Width属性优先于Stretch属性,如果设置 Height, Width 以及Stretch,会导致 Stretch被忽略。

  因此,尽管在设计时指定了属性值,布局系统依然需要重新计算每个子元素在界面上的实际大小,位置,边距等值,这些值被称为“FinalSize”。

4,基本属性:Alignment,Margin和Pading


  在设计UI时,WPF为我们提供了一些属性用于精确定位元素,其中最常用的有三个:Alignment(包括水平,垂直),Margin,Pading,具体用法如下:

名称 说明
Alignment 子元素在水平(垂直)方向的对齐方式,有左对齐,右对齐(顶端对齐,底部对齐),中间对齐,拉伸填充等四种方式。
Margin 用于指定元素与其子级或同级之间的距离,包括上下左右四个值。也可通过使用 Margin="20" 同时指定四个值。
Pading

Padding 在大多数方面类似于 Margin,只有少数元素有(公开),用于将子元素的有效大小增大指定的厚度。

5,附加属性


  通过上面我们了解到子元素通过一些属性值的设置实现在面板上布局,比如Alignment对齐属性,Dock停靠排列属性。这些属性不属于子元素本身,而依赖与所在的父元素。比如同样是Button,在DockPanel中有Dock属性,而在Grid中就没有。这些属性的存在依赖与父元素,在WPF中称做“附加属性”。

  附加属性的用途是允许不同的子元素为实际在父元素中定义的属性指定唯一值,目的是让子元素通知父元素它将如何在界面中呈现。如上面提到的DockPanel.Dock 属性,因为它将在 DockPanel 中包含的元素上设置,而不是在 DockPanel 本身设置。注意,相对于子元素,父元素提供的附加属性相当于全局属性。

6,布局与性能


  通过上面我们了解到,当给界面元素的布局属性赋值时,布局系统需要重新计算和排列所有子元素的“FinalSize”(因为改变影响不可知)。这是一个递归的过程。如果不注意,可能会带来性能问题。因此在设计时应注意下面几点:

  1,应注意哪些属性值更改会引起执行布局系统的递归更新;

  2,如有可能,应使用 RenderTransform 而不要使用 LayoutTransform;

  3,避免不必要地调用 UpdateLayout,因为UpdateLayout强制调用布局系统的递归更新;

  4,当包含大量元素集合时,请使用 VirtualizingStackPanel虚拟化元素;

7,总结


  通过本文,我们大概了解了WPF的布局系统,常用的布局面板,与布局有关的几个属性,以及设计开发UI时的注意事项。这些内容很多与WinForm中的相关概念相通,可以说是旧瓶装新酒,稍加思考,并不难理解;如果深入了解,会发现与WinForm截然不同。但作为初学者,如果能灵活使用文中所讲的知识点,深入理解注意点,对自身的提高还是很有帮助的。

WPF布局系统[转]的更多相关文章

  1. WPF教程二:理解WPF的布局系统和常用的Panel布局

    WPF的布局系统 了解元素的测量和排列方式是理解布局的第一步.在测量(measure)阶段容器遍历所有子元素,并询问子元素它们所期望的尺寸.在排列(arrange)阶段,容器在合适的位置放置子元素.理 ...

  2. WPF - 属性系统 (3 of 4)

    依赖项属性元数据 在前面的章节中,我们已经介绍了WPF依赖项属性元数据中的两个组成:CoerceValueCallback回调以及PropertyChangedCallback.而在本节中,我们将对其 ...

  3. 对比MFC资源文件谈谈WPF布局方式

    对比MFC资源文件谈谈WPF布局方式 MFC方式 对于传统的MFC基于UI的应用程序设计通常分两步走,首先是设计UI,使用的是RC文件,然后是代码文件,对RC文件进行操作,如下面Figure 1 的基 ...

  4. WPF快速入门系列(1)——WPF布局概览

    一.引言 关于WPF早在一年前就已经看过<深入浅出WPF>这本书,当时看完之后由于没有做笔记,以至于我现在又重新捡起来并记录下学习的过程,本系列将是一个WPF快速入门系列,主要介绍WPF中 ...

  5. WPF 获取系统 DPI 的多种方法

    原文:WPF 获取系统 DPI 的多种方法 WPF 获取系统 DPI 的多种方法 由于 WPF 的尺寸单位和系统的 DPI 相关,我们有时需要获取 DPI 值来进行一些界面布局的调整,本文汇总了一些 ...

  6. WPF布局原则

    WPF系统使用基于流布局的布局标准,开发人员创建与显示分辨率和窗口大小无关的用户界面.在不同显示器上可以进行很好的缩放. 首先来谈一谈布局原则: WPF窗口只能包含一个元素(Window元素属于内容控 ...

  7. WPF布局介绍(1)

    开局一张图,内容全靠...,本系列的文章, 主要针对刚入门.亦或是从 winform/bs转过来的开发人员快速入门的指南, 相对于其它一些文章中会详细的从项目如何建立到其实现的原理及组成部分, 本系列 ...

  8. WPF - 属性系统 (4 of 4)

    依赖项属性的重写 在基于C#的编程中,对属性的重写常常是一种行之有效的解决方案:在基类所提供的属性访问符实现不能满足当前要求的时候,我们就需要重新定义属性的访问符. 但对于依赖项属性而言,属性执行逻辑 ...

  9. WPF - 属性系统 (2 of 4)

    属性更改回调 前一章的示例中,对各个参数的设置都非常容易理解.如果我们仅仅需要创建一个独立的依赖项属性,那么上面所提到的创建依赖项属性的基础知识足以满足需求.但是事情往往并非如此完美.在一个系统中,很 ...

随机推荐

  1. ModelState用法

    ModelState.AddModelError:添加错误信息 ModelState是一个字典类型,这句话的作用是向ModelState中添加一条错误信息,第一个参数是Key,第二个参数是Value. ...

  2. 大话string

    最近看完大话string之后深有感悟,虽然写c#不知不觉的已经写了四年了,但是很多原理也一直不太明白,最近看完这个才算略微明白了一些. string类型有2个重要的特性,一致性和驻留性. 一致性就是说 ...

  3. hdu 1043 pku poj 1077 Eight (BFS + 康拓展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 http://poj.org/problem?id=1077 Eight Time Limit: 1000 ...

  4. ISNULL

    ISNULL 使用指定的替换值替换 NULL. 语法ISNULL ( check_expression , replacement_value ) 参数check_expression 将被检查是否为 ...

  5. [XJOI NOI2015模拟题13] C 白黑树 【线段树合并】

    题目链接:XJOI - NOI2015-13 - C 题目分析 使用神奇的线段树合并在 O(nlogn) 的时间复杂度内解决这道题目. 对树上的每个点都建立一棵线段树,key是时间(即第几次操作),动 ...

  6. 10个基于 Ruby on Rails 构建的顶级站点

    本文系国内 ITOM 行业领军企业 OneAPM 工程师翻译整理自 Raviraj Hegde 的文章 Top Sites Built with Ruby on Rails. 就其本身而言,Ruby ...

  7. Django单元测试(一)

    Django测试框架非常简单,首选方法是使用python标准库中的unittest模块. Writing tests Django的单元测试使用python的unittest模块,这个模块使用基于类的 ...

  8. 使用智遥工作流,优化SAP请购流程

    传统请购流程,都是用户在SAP系统中填写请购单,然后再打印出来,递交给上级领导审批.领导审批完了,再到SAP系统中更新release标识.若中途请购单内容需要变更,则需要重新打印,审批. 智遥工作流, ...

  9. ActionBar官方教程(6)把图标变成一个返回到上级的按钮,同一个app间,不同app间,不同fragment间

    Navigating Up with the App Icon Enabling the app icon as an Up button allows the user to navigate yo ...

  10. Android 内核初识(3)init进程

    init是一个进程,确切地说,它是Linux系统中用户空间的第一个进程.由于Android是基于Linux内核的,所以init也是Android系统中用户空间的第一个进程,它的进程号是1.作为天字第一 ...