转自: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. EL四大作用域 9个jsp对象有效范围 及 对应的类

    java中request,session,application的作用范围 page,request,session,application四者的作用范围: page的作用范围是当前页面:对应El表达 ...

  2. homework-Agile Software Development

    对敏捷开发的一些思考 这周的作业是对敏捷开发的相关阅读和思考. 在阅读的过程中,可以看到作者是一位具有丰富编程经验的大师.在开发的经历中,作者经历了极限编程等开发过程,但是在作者的多年经验中,作者还是 ...

  3. SpringMVC最基础配置

    SpringMVC和Struts2一样,是前后台的一个粘合剂,struts2用得比较熟悉了,现在来配置一下SpringMVC,看看其最基础配置和基本使用.SpriingMVC不是太难,学习成本不高,现 ...

  4. Android常用的工具类(转)

    主要介绍总结的Android开发中常用的工具类,大部分同样适用于Java.目前包括HttpUtils.DownloadManagerPro.ShellUtils.PackageUtils.Prefer ...

  5. 关于http客户端常见错误"警告:Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is rec"

    在开发过程中,经常得写http客户端测试接口服务,今天在使用过程中出现了这样的一个警告: 警告: Going to buffer response body of large or unknown s ...

  6. Python中zip()函数用法

    定义:zip([iterable, …])zip()是Python的一个内建函数,它接受一系列可迭代的对象作为参数,将对象中对应的元素打包成一个个tuple(元组),然后返回由这些tuples组成的l ...

  7. 【弱省胡策】Round #5 Handle 解题报告

    这个题是我出的 sb 题. 首先,我们可以得到: $$A_i = \sum_{j=i}^{n}{j\choose i}(-1)^{i+j}B_j$$ 我们先假设是对的,然后我们把这个关系带进来,有: ...

  8. WPS目录制作方法

    学校安排我进行电子技术校本教材的后期制作,汇总完全部文字后,需要编辑一个全书目录,进过一番摸索,使用WPS2009圆满完成了此次任务,愿与诸君共享. 1.显示大纲工具栏 打开“视图”——“工具栏”—— ...

  9. C++的表驱动法

    目的:使用表驱动法,替换复杂的if/else和switch/case语句. 说明:JS 等其他语言也都支持的. 表驱动发示例:http://blog.csdn.net/zhouyulu/article ...

  10. 转载爱哥自定义View系列--文字详解

    FontMetrics FontMetrics意为字体测量,这么一说大家是不是瞬间感受到了这玩意的重要性?那这东西有什么用呢?我们通过源码追踪进去可以看到FontMetrics其实是Paint的一个内 ...