很全面wpf布局基础


WPF学习(3)布局

今天我们来说说WPF的布局。我们知道WinForm的布局主要是采用基于坐标的方式,当窗口内容发生变化时,里面的控件不会随之动态调整,这就造成了一个很不好的用户体验。而WPF为了避免这个缺点,采用了基于流的这种灵活的布局方式(WinForm在.net 2.0中也增加了对flow-based的支持)。工欲善其事,必先利其器。首先,我们来看看WPF的布局控件主要有哪些。然后,了解下主要用于构成复杂控件的原始控件。最后说说关于内容溢出的处理办法。

1.布局控件

 WPF常用的布局控件主要有这么几个:Grid、StackPanel、Canvas、DockPanel、WrapPanel,它们都继承自Panel抽象类。

1.1Grid

Grid应该算是WPF中最常用的布局控件了。新建一个窗口可看到Grid是作为其默认的布局控件的。它的效果类似html中的Table,只不过在外观上Grid默认是没有边框的。我们可以在Visual Studio中的Xaml设计器上快速的创建表格,如下图所示:

很全面wpf布局基础_第1张图片

通过Xaml设计器设计,会自动为我们生成布局代码,值都是精确的,我们可以适当微调。当然,直接手写Xaml也可以达到同样的效果,下面我们来用C#代码来实现这样的布局:

  View Code

 上面代码中,在设置Grid的行高列宽时使用的是“*”,这就要我们了解下宽带和高度可以有哪些值。先来说下它们的单位:

很全面wpf布局基础_第2张图片

像素是默认单位,当使用其它三种时也会自动转换为像素。

对于Grid的行高和列宽我们可以设置三种值:

  1.绝对值: double类型的值加单位,单位可以有上图几种,省略不写默认为px,不会随着容器的改变而改变

  2.比例值 :double类型的值加星号“*”,当是“1*”时,“1”可以省略,计算的是在所有比例值中所占的比例,会动态调整

  3.自动值 :字符串“Auto”,它会根据实际的高度或者宽度来自动调整

注意:在WPF也有一个Table类,它是用来文档显示,而此处的Grid是用来界面显示的。

1.2StackPanel

 StackPanel正如它的名字一样,默认的情况下,它的子元素会从上到下排列,当然我们可以控制它的Orientation属性控制排列方向。Orientation属性有两个值一个Horizontal,一个是Vertical(默认)。看下图:

很全面wpf布局基础_第3张图片

StackPanel还有一个FlowDirection,它一般结合Orientation的值为Horizontal来使用,用来控制元素在水平方向上的排列方式。上图的Xaml代码:

  View Code

1.3Canvas

 Canvas相对于其它的布局控件来说,是有点儿特殊的,其它布局控件基本上都是基于流的,而它是基于坐标的。

Canvas有四个用于定位的附加属性Left、Top、Right和Bottom,分别水平方向(X轴)两个,竖直方向(Y轴)两个。

需要注意的一点是:当在一个方向同时设置了两个附加属性时,Left会覆盖Right,Top会覆盖Bottom。这样,排列组合可以有四种方式。还有一个zindex来控制Z轴,在Sliverlight中作为了Canvas的附加属性(Canvas.zindex),而在WPF中作为了Panel的附加属性(Panel.zindex)。如下图所示:

很全面wpf布局基础_第4张图片

默认情况下,后面的元素会盖住前面的元素,也就是button2会盖住button1,通过修改Panel.zindex的值来控制谁显示在前面。

1.4DockPanel

DockPanel可以让元素停靠在面板的某一边,然后拉伸元素以填满全部的宽度或高度。它有一个Dock属性用来设置停靠的位置,有Left、Top、Right和Bottom四个值。先来看下效果:

需要注意的是,DockPanel没有Fill属性,但是默认情况会将最后的子元素用来填充剩余空间,除非将其LastChildFill设为False,如下图所示:

与StackPanel一样,任何元素的拉伸都是有其Horizontal或者Vertical属性为Stretch造成,当设置为其它时又是又一番样子,请看下图:

Xaml代码如下:

  View Code

 

 其实仔细说来,DockPanel的功能要比StackPanel要强。当我们把DockPanel的LastChildFill设为False时,可以实现像StackPanel一样的布局。

先看图:

很全面wpf布局基础_第5张图片

Xaml代码:

  View Code

1.5WrapPanel

 WrapPanel在可能的空间中,一次以一行或者一列的形式布置控件元素。与StackPanel类似,WrapPanel也有Orientation属性来控制布局方向,不过它默认值是Horizontal(StackPanel默认是Vertical)。

当你为一行或一列中的第一个元素设置高度或宽度时,该行或该列的高度或宽度默认也设为该值,这是由元素的Horizontal和Vertical的值默认为Stretch导致的。我们可以认为来修改,如下图所示:

当你在伸缩窗口时,元素会自动调整。

Xaml代码:

  View Code

 WrapPanel也有和StackPanel一样的FlowDirection属性,功能一样,不在赘述。

2.原始面板

这里说的原始面板是指大部分位于System.Windows.Controls.Primitives 命名空间下的布局控件,主要有这么几个TabPanel、ToolBarOverFlowPanel、UniformGrid,还有一个ToolBarTray是位于System.Windows.Controls命名空间的,它们主要用于构成其他更复杂控件的一部分的基类和控件。关于该命名空间,可查看MSDN 。本节和模板Template联系紧密,我们将在模板时细说。这里以TabPanel为例,简单说明下。由于TabPanel是构成TabControl的内部的默认的布局控件,所以我们需要用Blend解剖TabControl来看下它的模板:

  View Code

 

我们发现TabControl主要是由Header和Content部分构成的,Header就是由我们这里的TabPanel来充当的,而Content则由ContentPresenter来充当。知道了这些,我们可以做一个另类的TabControl了,看下效果图:

很全面wpf布局基础_第6张图片

Xaml代码:

  View Code

 这里只是简单改了布局,用StackPanel来简单替换了TabPanel,当然根据需要,也可以用其它的布局控件来替换了。

3.内容溢出

内建的面板会尽可能的满足其子元素的尺寸要求,然而有时候,我们不能不压缩子元素的尺寸,这样导致子元素的内容溢出。处理内容溢出主要有以下几种方式:

3.1剪辑(Clipping)

通过设置ClipToBounds属性来控制是否让元素超出边界部分在外边界显示。尽管这个属性是所有UIElement及其子类都有的属性,但是只对Canvas起作用,其它布局控件都会剪辑掉超出             部分。当然,ClipToBounds属性也可以对自己内容进行剪辑。举个例子说明:

很全面wpf布局基础_第7张图片

这是当我们MouseOver的时候Button的样子,此时ClipToBounds默认为False,我们将它改为True然后再MouseOver到Button上看下效果:

发现溢出部分被剪辑掉了。Xaml代码如下:

  View Code

 这里需要注意的一点是:剪辑是在RenderTransform生效之前发生的。

3.2滚屏(Scrolling)

主要是通过ScrollViewer控件来实现的,属性主要有HorizontalScrollBarVisibility(默认值为auto)和VerticalScrollBarVisibility(默认为Visible)。直接看例子:

  View Code

 效果图如下:

 3.3缩放(scalling)

说到缩放,我们首先会想到ScaleTransform,它是相对于元素的自身大小来进行缩放,相对于滚屏方式,需要写很多额外的代码,有没有和ScrollViewer一样使用简单的控件来实现缩放的效果呢?有,那就是Viewbox,那是一种类似于只有一个子元素的面板,是一种Decorator装饰类,通过它的Stretch属性来实现任意内容的缩放。假如我们在一个300*300的窗口有一个300*400的大号按钮,窗口只能显示其中的的一部分,现在我们可以用Viewbox来缩放让它完全显示在窗口上面,先看原图:

很全面wpf布局基础_第8张图片

再看使用Viewbox,设置其Stetch属性后的效果:

很全面wpf布局基础_第9张图片

经过缩放后,已经能够完全显示了。Xaml代码如下:

  View Code

 4.总结

WPF布局牵涉的内容很多,只有在平时不断积累才能渐趋完善!

你可能感兴趣的:(很全面wpf布局基础)