前言:对于客户端开发,界面布局这个问题应该是设计软件之初前端最先考虑的,尤其是设计一些工具性小软件。下面记录下wpf中常用布局控件及一些使用。
一、简介
wpf中常用到的布局控件基本上有如下这些:
继承自Panel的这些布局控件可以包含多个子控件,另外两种只能包含一个控件。
二、常用布局控件
2.1 Grid
由行列组成的灵活的网络区域。游戏中的消消乐,小时候学习写字的田字格,都是这东西。但是笔者更愿意用excel作比较,在制作excel的时候,我们经常需要调整单元格的长宽等以适应放入表格中的内容(文字、图片等),同样的,我们在设计Grid的时候也需要设置Grid的一些长宽等格式。
默认情况下,每个行列构成的一个单元格的长宽会自适应把父级控件平分。
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition />
- <RowDefinition />
- <RowDefinition />
- <RowDefinition />
- Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition />
- <ColumnDefinition />
- <ColumnDefinition />
- Grid.ColumnDefinitions>
-
- <TextBlock FontSize="20" FontWeight="Bold" >2005 Products ShddddddddddddddddddippedTextBlock>
- <TextBlock FontSize="12" FontWeight="Bold" Grid.Row="1" Grid.Column="0">Quarter 1TextBlock>
- <TextBlock FontSize="12" FontWeight="Bold" Grid.Row="1" Grid.Column="1">Quarter 2TextBlock>
- <TextBlock FontSize="12" FontWeight="Bold" Grid.Row="1" Grid.Column="2">Quarter 3TextBlock>
- <TextBlock Grid.Row="2" Grid.Column="0">50000TextBlock>
- <TextBlock Grid.Row="2" Grid.Column="1">100000TextBlock>
- <TextBlock Grid.Row="2" Grid.Column="2">150000TextBlock>
- <TextBlock FontSize="16" FontWeight="Bold" Grid.ColumnSpan="3" Grid.Row="3">Total Units: 300000TextBlock>
- Grid>
可以通过设置Grid中的一些属性来实现一些效果,比如
<Grid VerticalAlignment="Top" HorizontalAlignment="Left" ShowGridLines="True">
这样行列就不会自动平分父级大小了, 而且每个行列构成的单元格大小会根据里面内容进行自动适应(但是单元格长宽有一定限制,)。上面设置了VerticalAlignment和HorizontalAlignment属性,这样内容就会在每个单元格的左上角进行停靠,所以之前多余的那些空间就会自动被优化掉了。还有很多属性大家可以去研究。
也就是说在grid的布局中,容器是默认居中展开的,若设置宽度后,也是默认居中的。
Grid面板支持以下三种设置尺寸的方式:
名称 | 说明 |
绝对设置尺寸方式(固定大小) | 使用设备无关单位准确地设置尺寸,就是给一个实际的数字,但通常将此值指定为整数。这是最无用 的策略,因为这种策略不够灵活,难以适应内容大小和容器大小的改变,而且难以处理本地化。如果控件大小超过了行列的大小仅仅会显示控件的一部分内容,多余的部分会被隐藏; |
自动设置尺寸方式 | 值为Auto,实际作用就是取实际控件所需的最小值,每行和每列的尺寸刚好满足需要,这是最有用 的尺寸设置方式。 |
按比例设置尺寸方式 | 按比例将空间分割到一组行和列中。这是对所有行和列的标准设置。通常值为*或N*,实际作用就是取尽可能大的值,当某一列或行被定义为*则是尽可能大,当出现多列或行被定义为*则是代表几者之间按比例方设置尺寸。 |
为了获得最大的灵活性,可混合使用这三种尺寸设置方式。例如,创建几个自动设置尺寸的行,然后通过按比例设置尺寸的方式让最后的一行或两行充满剩余的空间,这通常是很有用的。
可通过设置ColumnDefinition对象的Width属性或者RowDefinition对象的Height属性来确定尺寸设置方式。
(1)设置100设备无关单位的绝对宽度:
<ColumnDefinition Width="100">ColumnDefinition>
(2)使用自动尺寸设置方式,需要使用Auto值,会根据内容自动设置size
<ColumnDefinition Width="Auto">ColumnDefinition>
(3)使用按比例尺寸设置方式,需要使用星号(*),会对绝对宽度和自动宽度剩下的内容进行按比例尺寸设置size
<ColumnDefinition Width="*">ColumnDefinition>
如果希望不均匀的分割剩余空间,可指定权重,权重必须放在星号之前。例如,如果有两行是按比例设置尺寸,并希望第一行的高度是第二行高度的一半,那么可以使用如下设置来分配剩余空间:
- <RowDefinition Height="*">RowDefinition>
- <RowDefinition Height="2*">RowDefinition>
2.2 UniformGrid
提供一种在网格(网格中的所有单元格都具有相同的大小)中排列内容的方法。其实是一种简化的网格布局,当控件添加到 UniformGrid 时,它们会排列在一个网格模式中,该网格模式会自动调整以使控件之间的距离保持均匀。单元格的数目将进行调整,以适应控件的数目。例如,如果四个控件添加到 UniformGrid 中,它们将安排在包含四个单元格的网格中。
- <UniformGrid>
- <Button Content="ButtonA" />
- <Button Content="ButtonB" />
- <Button Content="ButtonC" />
- <Button Content="ButtonD" />
- <Button Content="ButtonE" />
- <Button Content="ButtonF" />
- <Button Content="ButtonG" />
- <Button Content="ButtonH" />
- <Button Content="ButtonI" />
- <Button Content="ButtonJ" />
- UniformGrid>
在上图中,虽然button个数为10个,但是仍然会生成4*4个单元格,随着窗体大小变化,各Button的大小自适应变化,位置不变。
在使用UniformGrid的时候:
2.3 StackPanel
将子元素排列成水平或垂直的一行,属于布局控件,通俗说叫栈式面板。可将包含的元素在水平或垂直方向排成一条线,当移除一个元素后,后面的元素会自动向前填充空缺。
说明:StackPanel(栈面板),可以将元素排列成一行或一列,其特点是:每个元素各占一行或者一列,Orientation属性指定排列方式:Vertical(垂直)、Horizontal(水平),默认情况下,水平排列时,每个元素都与面板一样高;垂直排列时,每个元素都与面板一样宽。如果包含的元素超过了面板空间,它只会截断多出的内容。 元素的Margin属性用于使元素之间产生一定得间隔,当元素空间大于其内容的空间时,剩余空间将由HorizontalAlignment和 VerticalAlignment属性来决定如何分配。
试想一下,如果StackPanel的Orientation属性设置成了Vertical(垂直),那么元素就会垂直方向一个挨着一个排列,这个时候元素的自然就没法垂直拉伸了,如果能垂直拉伸的话,那只能显示一个元素了。
2.4 WrapPanel
按从左到右的顺序位置定位子元素,在包含框的边缘处将内容切换到下一行。可自动折行面板,内部元素在排满一行后能够自动折行,类似于Html中的流式布局。
该容器可以看做自动换行功能的StackPanel容器,当我们把窗口的宽度Width="800"改Width="80"时,内部采用的是流式布局,在流延伸的方向上WrapPanel会排列尽可能多的控件,排不下的会新起一行或一列继续排列。
2.5 DockPanel
定义一个区域从中可以按相对位置水平或垂直排列各个子元素。与StackPanel一样,任何元素的拉伸是由于它们的HorizontalAlignment或者VerticalAlignment的值为Strech造成的。如果元素不想填充DockPanel给它们的空间,这些元素可以选择不同的对齐方式。DockPanel支持让元素简单地停靠在整个面板的某一条边上,然后拉伸元素以填满全部宽度或高度。它也支持让一个元素填充其他已停靠元素没有占用的剩余空间。
DockPanel对于在一个Window或者Page中布局顶层用户界面十分有用,尤其是当Window或Page中大量要停靠的元素是一些包含了内容的其他的面板时。子元素添加到DockPanel中的顺序是有影响的,因为每个子元素得到的是剩余的位于边缘的停靠空间。但是DockPanel对子元素无数量限制,当多个元素朝同一个方向停靠时,它们会被简单地排列在某个方向上。
子元素的HorizontalAlignment有时候就不好使了,需要使用DockPanel.Dock进行停靠设置。
2.6 ScrollViewer
一个可以滚动的控件。它使得大量内容在有限容器内显示成为可能。ScrollViewer有一个滚动条设置的属性,在垂直方向有VerticalScrollBarVisibility=“Hidden”。有四种取值,分别是:
Visible:显示滚动条
Hidden:隐藏滚动条,用光标仍然可以滚动内容
Disable:隐藏滚动条,用光标不可以滚动内容
Auto:只有当内容超出容器时才会显示滚动条
以上四种取值均可用滑轮滚动内容。
同样的,在水平方向,也有HorizontalScrollBarVisibility属性。
自定义滚动
如图所示的窗口里面放置了四个Button控件,在点击滚动条上下按键时无法保证让某一个控件完全显示,此时只要将ScrollViewer的CanContentScroll属性设为True即可。
但是这个属性只有部分容器可以使用,例如StackPannel
- <ScrollViewer Margin="3" CanContentScroll="True">
- <StackPanel Margin="2">
- <Button Name="Button1" Width="100" Height="100" Content="Button1"/>
- <Button Name="Button2" Width="100" Height="100" Content="Button2"/>
- <Button Name="Button3" Width="100" Height="100" Content="Button3"/>
- <Button Name="Button4" Width="100" Height="100" Content="Button4"/>
- StackPanel>
- ScrollViewer>
2.7 ViewBox
ViewBox这个控件通常和其他控件结合起来使用,是WPF中非常有用的控件。定义一个内容容器。ViewBox组件的作用是拉伸或延展位于其中的组件,以填满可用空间,使之有更好的布局及视觉效果。一个 Viewbox中只能放一个控件。如果多添加了一个控件就会报错。
组件常用属性:
Child:获取或设置一个ViewBox元素的单一子元素。
Stretch:获取或设置拉伸模式以决定该组件中的内容以怎样的形式填充该组件的已有空间。
说明:这个拉伸有可能会将控件的字体同样拉伸,可能有时候会在视觉上不那么协调。笔者研究了几个大厂的桌面软件,包括钉钉、微信、QQ、网易云音乐等,发现他们都没有用这种方式(当然他们也不是用WPF开发的),笔者测量了这几个桌面软件在正常大小及最大化后子控件(如Button)的尺寸,是没有变化的。
2.8 Border
Border 控件是一个装饰器控件,您可以使用它在另一个元素周围绘制边框、背景或什至两者。由于 WPF 面板不支持在其边缘周围绘制边框,因此边框控件可以帮助您实现这一点,只需通过边框控件包围例如面板即可。
使用上述边框的简单示例可能如下所示:
- <Grid Margin="10">
- <Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
- <StackPanel Margin="10">
- <Button>Button 1Button>
- <Button Margin="0,10">Button 2Button>
- <Button>Button 3Button>
- StackPanel>
- Border>
- Grid>
这个在现在这种扁平化设计理念下还是挺实用的,一组控件放一个这东西,比如下面钉钉的布局,看起来比较整洁。
三、引用文献
3.1 WPF 下的自定义控件以及 Grid 中控件的自适应_雪中亮的博客-CSDN博客_wpf控件自适应父窗体
3.2 https://www.jb51.net/article/238833.htm
3.3 WPF布局之Grid - 灰信网(软件开发博客聚合)
3.4 https://blog.csdn.net/BYH371256/article/details/125271398