一 写在开头
1.1 写在开头
评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好。
1.2 本文内容
本文主要内容为WPF中的常用布局,大部分内容转载至https://blog.csdn.net/woshisunjiale/article/details/54136323,代码片段可能有所不同。
二 WPF中的常用布局
因为项目需要,所以得学习WPF开发。WPF使软件界面和逻辑相分离,手写xaml进行程序UI的开发是件很惬意的事情。从这点来说WPF要比Qt和GTK+要好。当然了,如果其能跨平台甚至开源那就更好了。但是,商业有商业自身的规律。
2.1 Canvas布局
Canvas是一个类似于坐标系的面板,所有的元素通过设置坐标来决定其在坐标系中的位置。具体表现为使用Left、Top、Right、 Bottom附加属性在Canvas中定位控件。
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <Canvas> 7 <Button Canvas.Left="50" Canvas.Top="50" Content="Button 1"></Button> 8 <Button Canvas.Right="50" Canvas.Top="50" Content="Button 2"></Button> 9 <Button Canvas.Left="50" Canvas.Bottom="50" Content="Button 3"></Button> 10 <Button Canvas.Right="50" Canvas.Bottom="50" Content="Button 4"></Button> 11 </Canvas> 12 </Grid> 13 </Window>
注意:如果同时设置 Canvas.Left="50"Canvas.Right="50",则以Canvas.Left="50"为准。如果同时设置Canvas.Top="50" Canvas.Bottom="50",则以Canvas.Top ="50"为准。(别这么丧心病狂地同时写Left和Right,请遵循基本的编程逻辑)
2.2 StackPanel布局
StackPanel将控件按照行或列来顺序排列,但不会换行。通过设置面板的Orientation属性设置了两种排列方式:横排(Horizontal默认的)和竖排(Vertical),默认为竖排(Vertical)。
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <StackPanel Name="stackpanel1" Orientation="Horizontal"> 7 <Button Content="Button1"></Button> 8 <Button Content="Button2"></Button> 9 <Button Content="Button3"></Button> 10 </StackPanel> 11 <StackPanel Name="stackpanel2" Orientation="Vertical"> 12 <Button Content="Button4"></Button> 13 <Button Content="Button5"></Button> 14 <Button Content="Button6"></Button> 15 </StackPanel> 16 <StackPanel Name="stackpanel3" Orientation="Horizontal" FlowDirection="RightToLeft"> 17 <Button Content="Button7"></Button> 18 <Button Content="Button8"></Button> 19 <Button Content="Button9"></Button> 20 </StackPanel> 21 </Grid> 22 </Window>
注意:Orientation="Horizontal"时,设置FlowDirection属性为RightToLeft,,则元素将从右向左排列。
2.3 DockPanel布局
DockPanel支持让元素简单地停靠在整个面板的某一条边上,然后拉伸元素以填满全部宽度或高度。它也支持让一个元素填充其他已停靠元素没有占用的剩余空间。
DockPanel有一个Dock附加属性,因此子元素用4个值来控制她们的停靠:Left、Top、Right、Bottom。Dock没有Fill值。作为替代,最后的子元素将加入一个DockPanel并填满所有剩余的空间,除非DockPanel的LastChildFill属性为false,它将朝某个方向停靠。
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <DockPanel> 7 <Button Content="上" DockPanel.Dock="Left"></Button> 8 <Button Content="下" DockPanel.Dock="Bottom"></Button> 9 <Button Content="左" DockPanel.Dock="Left"></Button> 10 <Button Content="右" DockPanel.Dock="Right"></Button> 11 </DockPanel> 12 </Grid> 13 </Window>
设置LastChildFill属性为false
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <DockPanel LastChildFill="False"> 7 <Button Content="上" DockPanel.Dock="Left"></Button> 8 <Button Content="下" DockPanel.Dock="Bottom"></Button> 9 <Button Content="左" DockPanel.Dock="Left"></Button> 10 <Button Content="右" DockPanel.Dock="Right"></Button> 11 </DockPanel> 12 </Grid> 13 </Window>
2.4 WrapPanel布局
WrapPanel布局面板将各个控件按照一定方向罗列,当长度或高度不够时自动调整进行换行换列。
Orientation="Horizontal"时各控件从左至右罗列,当面板长度不够时,子控件就会自动换行,继续按照从左至右的顺序排列。
Orientation="Vertical"时各控件从上至下罗列,当面板高度不够时,子控件就会自动换列,继续按照从上至下的顺序排列。
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <WrapPanel Orientation="Horizontal"> 7 <Button Content="Button 150" Width="150"></Button> 8 <Button Content="Button 200" Width="200"></Button> 9 <Button Content="Button 150" Width="150"></Button> 10 <Button Content="Button 200" Width="200"></Button> 11 <Button Content="Button 150" Width="150"></Button> 12 <Button Content="Button 200" Width="200"></Button> 13 <Button Content="Button 150" Width="150"></Button> 14 </WrapPanel> 15 </Grid> 16 </Window>
2.5 Grid布局
Grid允许我们通过自定义行列来进行布局,这类似于表格.通过定义Grid的RowDifinitions和ColumnDifinitions来实现对于表格行和列的定义,元素根据附加属性Grid.Row和Grid.Column确定自己的位置。
1)Grid的列宽与行高可采用固定、自动、按比列三种方式定义
第一种,固定长度——值为一个确定的数字
第二种,自动长度——值为Auto,实际作用就是取实际控件所需的最小值
第三种,比例长度——*表示占用剩余的全部宽度;两行都是*,将平分剩余宽度;一个2*,一个*,则前者占剩余全部宽度的2/3,后者占1/3;依此类推
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <Grid.RowDefinitions> 7 <RowDefinition Height="40"></RowDefinition> 8 <RowDefinition Height="Auto"></RowDefinition> 9 <RowDefinition Height="2*"></RowDefinition> 10 <RowDefinition Height="*"></RowDefinition> 11 </Grid.RowDefinitions> 12 <Button Grid.Row="0" Content="Button 1"></Button> 13 <Button Grid.Row="1" Content="Button 2"></Button> 14 <Button Grid.Row="2" Content="Button 3"></Button> 15 <Button Grid.Row="3" Content="Button 4"></Button> 16 </Grid> 17 </Window>
2) 合并行或列
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <Grid.RowDefinitions> 7 <RowDefinition Height="40"></RowDefinition> 8 <RowDefinition Height="Auto"></RowDefinition> 9 <RowDefinition Height="2*"></RowDefinition> 10 <RowDefinition Height="*"></RowDefinition> 11 </Grid.RowDefinitions> 12 <Button Grid.Row="0" Content="Button 1"></Button> 13 <Button Grid.Row="1" Content="Button 2"></Button> 14 <Button Grid.Row="2" Grid.RowSpan="2" Content="Button 3"></Button> 15 </Grid> 16 </Window>
3)GridSplitter重新分布Grid控件的列间距或行间距。(类似于WinForm中SplitContainer)
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <Grid.RowDefinitions> 7 <RowDefinition Height="*"></RowDefinition> 8 <RowDefinition Height="3"></RowDefinition> 9 <RowDefinition Height="*"></RowDefinition> 10 </Grid.RowDefinitions> 11 <Button Grid.Row="0" Content="Button"></Button> 12 <GridSplitter Grid.Row="1" HorizontalAlignment="Stretch"></GridSplitter> 13 <Button Grid.Row="2" Content="Button"></Button> 14 </Grid> 15 </Window>
2.6 UniformGrid布局
UniformGrid就是Grid的简化版,每个单元格的大小相同,不需要定义行列集合。每个单元格始终具有相同的大小,每个单元格只能容纳一个控件。
若不设置RowsColums,则按照定义在其内部的元素个数,自动创建行列,并通常保持相同的行列数。若只设置Rows则固定行数,自动扩展列数。若只设置Colums则固定列数,自动扩展行数。
UniformGrid 中没有Row和Column附加属性,也没有空白单元格。
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <UniformGrid> 7 <Button Content="Button"></Button> 8 <Button Content="Button"></Button> 9 <Button Content="Button"></Button> 10 <Button Content="Button"></Button> 11 <Button Content="Button"></Button> 12 <Button Content="Button"></Button> 13 <Button Content="Button"></Button> 14 </UniformGrid> 15 </Grid> 16 </Window>
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <UniformGrid Columns="2"> 7 <Button Content="Button"></Button> 8 <Button Content="Button"></Button> 9 <Button Content="Button"></Button> 10 <Button Content="Button"></Button> 11 <Button Content="Button"></Button> 12 <Button Content="Button"></Button> 13 <Button Content="Button"></Button> 14 </UniformGrid> 15 </Grid> 16 </Window>
2.7 ScrollViewer布局
ScrollViewer是带有滚动条的面板。在ScrollViewer中只能有一个子控件,若要显示多个子控件,需要将一个附加的 Panel控件放置在父 ScrollViewer中。然后可以将子控件放置在该控件中。
HorizontalScrollBarVisibility水平滚动条是否显示默认为Hidden
VerticalScrollBarVisibility垂直滚动条是否显示 默认为Visible。
一般我们都会设置 HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
意思是:当内容超出可视范围时,才显示横向/纵向滚动条
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> 7 <Button Content="Button" Width="800" Height="800"></Button> 8 </ScrollViewer> 9 </Grid> 10 </Window>
2.8 ViewBox布局
Viewbox的作用是拉伸或延展位于其中的组件,以填满可用空间。在Viewbox中只能有一个子控件,若要显示多个子控件,需要将一个附加的Panel控件放置在父Viewbox中。然后可以将子控件放置在该控件中。
常用属性:
Stretch:获取或设置拉伸模式以决定该组件中的内容以怎样的形式填充该组件的已有空间。具体设置值如下:
None:不进行拉伸,按子元素设置的长宽显示。
Uniform:按原比例缩放子元素,使得一边不足,另一边恰好填充
Fill:缩放子元素,使得子元素的长变为Viewbox的长,宽变为Viewbox的宽
UniformToFill:按原比例缩放子元素,使得子元素一边恰好填充,另一边超出Viewbox的区域
Stretch默认值为Uniform。
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <Grid.RowDefinitions> 7 <RowDefinition> 8 9 </RowDefinition> 10 </Grid.RowDefinitions> 11 <Grid.ColumnDefinitions> 12 <ColumnDefinition> 13 14 </ColumnDefinition> 15 </Grid.ColumnDefinitions> 16 <Viewbox Grid.Row="0" Grid.Column="0" Stretch="None"> 17 <Button Width="100" Height="50" Content="None"></Button> 18 </Viewbox> 19 <Viewbox Grid.Row="0" Grid.Column="1" Stretch="Uniform"> 20 <Button Width="100" Height="50" Content="Uniform"></Button> 21 </Viewbox> 22 <Viewbox Grid.Row="1" Grid.Column="0" Stretch="Fill"> 23 <Button Width="100" Height="50" Content="Fill"></Button> 24 </Viewbox> 25 <Viewbox Grid.Row="1" Grid.Column="1" Stretch="UniformToFill"> 26 <Button Width="100" Height="50" Content="UniformToFill"></Button> 27 </Viewbox> 28 </Grid> 29 </Window>
2.9 Border
Border 是一个装饰的控件,此控件用于绘制边框及背景,在Border中只能有一个子控件,若要显示多个子控件,需要将一个附加的Panel控件放置在父Border中。然后可以将子控件放置在该 Panel控件中。
常用属性:
Background: 背景色 ;
BorderBrush: 边框色 ;
BorderThickness: 边框宽度;
CornerRadius: 各个角 圆的半径;
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <Border Background="YellowGreen" BorderBrush="Black" BorderThickness="0, 2, 4, 6" CornerRadius="0, 10, 20, 30"></Border> 7 </Grid> 8 </Window>
三 精确定位的常用属性
在设计UI时,WPF为我们提供了一些属性用于精确定位元素,其中最常用的有三个:Alignment(包括水平,垂直),Margin,Padding,具体用法如下:
HorizontalAlignment: 子元素在水平方向的对齐方式,有左对齐,右对齐,中间对齐,拉伸填充等四种方式。
VerticalAlignment:子元素在垂直方向的对齐方式,有顶端对齐,底部对齐,中间对齐,拉伸填充等四种方式。
Margin:用于指定元素与其父级或同级之间的距离,包括上下左右四个值。也可通过使用 Margin="20"同时指定四个值。
Padding:用于指定元素与其子级之间的距离,包括上下左右四个值。也可通过使用Padding="20"同时指定四个值。
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <Grid.RowDefinitions> 7 <RowDefinition> 8 9 </RowDefinition> 10 <RowDefinition> 11 12 </RowDefinition> 13 </Grid.RowDefinitions> 14 <Button Grid.Row="0" Content="Center" HorizontalAlignment="Center"></Button> 15 <Button Grid.Row="1" Content="Left" HorizontalAlignment="Left"></Button> 16 <Button Grid.Row="2" Content="Right" HorizontalAlignment="Right"></Button> 17 <Button Grid.Row="3" Content="Stretch" HorizontalAlignment="Stretch"></Button> 18 </Grid> 19 </Window>
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <Border Background="YellowGreen"> 7 <Button Margin="0, 50, 100, 150"></Button> 8 </Border> 9 </Grid> 10 </Window>
1 <Window x:Class="WPF_Layout.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WPF-Layout" Height="350" Width="525"> 5 <Grid> 6 <Border Background="YellowGreen" Padding="0, 50, 100, 150"> 7 <Button ></Button> 8 </Border> 9 </Grid> 10 </Window>