收藏 分销(赏)

WPF布局全接触.doc

上传人:pc****0 文档编号:9011247 上传时间:2025-03-11 格式:DOC 页数:46 大小:822.50KB
下载 相关 举报
WPF布局全接触.doc_第1页
第1页 / 共46页
WPF布局全接触.doc_第2页
第2页 / 共46页
点击查看更多>>
资源描述
一. 摘要   首先很高兴这个系列能得到大家的关注和支持,这段时间一直在研究Windows Azure,所以暂缓了更新,同时也本着想把它写好、宁缺毋滥的精神,在速度上自然也就慢了下来,这篇文章拖拖拉拉也经历了十多天才发布出来(每天写一点),不过请大家放心,这个系列一定会继续写下去。由于自己才疏学浅且是对这些技术的使用总结和心得体会,错误之处在所难免,怀着技术交流的心态,在这里发表出来,所以希望大家能够多多指点,这样在使一部分人受益的同时也能纠正我的错误观点,以便和各位共同提高。   这篇文章主要是对WPF布局系统做一个较简单的介绍,大家都知道:UI是做好一个软件很重要的因素,如果没有一个漂亮的UI,再怎么强大的功能也会显得这个软件很脆弱且没有投资价值。本文以总分总的形式展开介绍:首先对WPF Panel做一个总体认识、然后讲解各Panel基本用法(分别用XAML和C#两种方式实现同一个功能,便于大家学习)、布局综合应用、自定义布局控件以及最后的总结,希望对大家有所帮助。 二. 本文提纲 · 1.摘要 · 2.本文提纲 · 3.总体介绍 · 4.Canvas · 5.StackPanel · 6.WrapPanel · 7.DockPanel · 8.Grid · 9.UniformGrid · 10.ViewBox · 11.Border · 12.ScrollViewer · 13.布局综合应用 · 14.自定义布局控件 · 15.本文总结 · 16.系列进度 · 17.相关代码 三. 总体介绍   WPF的布局控件都在System.Windows.Controls.Panel这个基类下面,使用 Panel 元素在WPF应用程序中放置和排列子对象。它具体包括哪些布局控件以及如何使用这些布局控件(分别用XAML和C#两种方式实现同一个功能)、如何开发自定义的布局控件,也就是本文所要讨论的范畴:     Panel具体继承关系详见下面类图:   如上图,公共属性太多了,就简单介绍几个常见的属性:Margin是元素与其他元素的外边距;Padding是指在本元素内部的元素内容与边缘的距离;前面这两个元素基本和ASP.NE中的Margin和Padding类似,只是定义大小的设置不同而已; FlowDirection属性标示元素的内容显示方向;Panel.ZIndex是相对于显示屏的Z轴坐标,用于调整层叠元素的显示先后;RenderTransform和LayoutTransform用来将缩放和旋转的变换应用到某个元素上。   一个Panel 的呈现是测量和排列Children子元素、然后在屏幕上绘制它们的过程。所以在布局的过程中会经过一系列的计算,那么Children 越多,执行的计算次数就越多。如果不需要较为复杂的 Panel(如 Grid和自定义复杂的Panel),则可以使用构造相对简单的布局(如 Canvas、UniformGrid等),这种布局可带来更好的性能。 如果有可能,我们应尽量避免不必要地调用 UpdateLayout方法。 每当Panel内的子元素改变其位置时,布局系统就可能触发一个新的处理过程。对此,了解哪些事件会调用布局系统就很重要,因为不必要的调用可能导致应用程序性能变差。   换句话说,布局是一个递归系统,实现在屏幕上对元素进行大小调整、定位和绘制,然后进行呈现。具体如下图,要实现控件0的布局,那么先要实现0的子控件01,02...的布局,要实现01的布局,那么得实现01的子控件001,002...的布局,如此循环直到子控件的布局完成后,再完成父控件的布局,最后递归回去直到递归结束,这样整个布局过程就完成了.   布局系统为 Children 集合的每个成员完成两个处理过程:测量处理过程(Measure)和排列处理过程(Arrange)。每个子 Panel 均提供自己的 MeasureOverride 和 ArrangeOverride 方法,以实现自己特定的布局行为。 四. Canvas   Canvas比较简单,只是一个存储元素的容器,它不会自动调整内部元素的排列及大小。不指定元素位置,元素将默认显示在画布的左上方。Canvas的主要用途是用来画图。Canvas默认不会自动裁减超过自身范围的内容,即溢出的内容会显示在Canvas外面,这是因为默认 ClipToBounds="False";我们可以通过设置ClipToBounds="True来裁剪多出的内容。 要实现的效果如下图(用XAML和C#实现同一效果): XAML代码实现: <Window xmlns=" xmlns:x=" x:Class="WPFLayoutDemo.CanvasDEMO" x:Name="Window" Title="CanvasDEMO" WindowStartupLocation="CenterScreen" Width="640" Height="480"> <Canvas Margin="0,0,0,0" Background="White"> <Rectangle Fill="Red" Stroke="Azure" Width="209" Height="159" Canvas.Left="310" Canvas.Top="181"/> <Ellipse Fill="Azure" Stroke="Green" Width="258" Height="97" Panel.ZIndex="1" Canvas.Left="165" Canvas.Top="145"/> </Canvas> </Window> C#代码实现: namespace WPFLayoutDemo { public partial class CanvasDEMOCodeBehind { public CanvasDEMOCodeBehind() { this.InitializeComponent(); Canvas canv = new Canvas(); //把canv添加为窗体的子控件 this.Content = canv; canv.Margin = new Thickness(0, 0, 0, 0); canv.Background = new SolidColorBrush(Colors.White); //Rectangle Rectangle r = new Rectangle(); r.Fill = new SolidColorBrush(Colors.Red); r.Stroke = new SolidColorBrush(Colors.Red); r.Width = 145; r.Height = 126; r.SetValue(Canvas.LeftProperty, (double)124); r.SetValue(Canvas.TopProperty, (double)122); canv.Children.Add(r); //Ellipse Ellipse el = new Ellipse(); el.Fill = new SolidColorBrush(Colors.Azure); el.Stroke = new SolidColorBrush(Colors.Azure); el.Width = 121; el.Height = 100; el.SetValue(Canvas.ZIndexProperty, 1); el.SetValue(Canvas.LeftProperty, (double)195); el.SetValue(Canvas.TopProperty, (double)191); canv.Children.Add(el); } } }   五. StackPanel   StackPanel就是将子元素按照堆栈的形式一一排列,通过设置面板的Orientation属性设置了两种排列方式:横排(Horizontal默认的)和竖排(Vertical)。纵向的StackPanel默认每个元素宽度与面板一样宽,反之横向亦然。如果包含的元素超过了面板空间,它只会截断多出的内容。 元素的Margin属性用于使元素之间产生一定得间隔,当元素空间大于其内容的空间时,剩余空间将由HorizontalAlignment和VerticalAlignment属性来决定如何分配。其他属性,大家可以看看如下类图: 要实现的效果如下图(用XAML和C#实现同一效果):   XAML代码实现: <Window xmlns=" xmlns:x=" x:Class="WPFLayoutDemo.StackPanelDEMO" x:Name="Window" Title="StackPanelDEMO" WindowStartupLocation="CenterScreen" Width="640" Height="480"> <StackPanel Margin="0,0,0,0" Background="White" Orientation="Vertical"> <Button Content="Top of Stack"/> <Button Content="Middle of Stack"/> <Button Content="Bottom Of Stack"/> </StackPanel> </Window> C#代码实现: namespace WPFLayoutDemo { public partial class StackPanelDEMOCodeBehind { public StackPanelDEMOCodeBehind() { this.InitializeComponent(); StackPanel sp = new StackPanel(); //把sp添加为窗体的子控件 this.Content = sp; sp.Margin = new Thickness(0, 0, 0, 0); sp.Background = new SolidColorBrush(Colors.White); sp.Orientation = Orientation.Vertical; //Button1 Button b1 = new Button(); b1.Content = "Top of Stack"; sp.Children.Add(b1); //Button2 Button b2 = new Button(); b2.Content = "Middle of Stack"; sp.Children.Add(b2); //Button3 Button b3 = new Button(); b3.Content = "Bottom of Stack"; sp.Children.Add(b3); } } }   六. WrapPanel   WrapPanel是一个非常简单的面板,从左至右按顺序位置定位子元素,如果排满断开至下一行。后续排序按照从上至下或从右至左的顺序进行。WrapPanel面板也提供了 Orientation属性设置排列方式,这跟上面的StackPanel基本相似。不同的是WrapPanel会根据内容自动换行。 要实现的效果如下图(用XAML和C#实现同一效果):   XAML代码实现: <Window xmlns=" xmlns:x=" x:Class="WPFLayoutDemo.WrapPanelDEMO" x:Name="Window" Title="WrapPanelDEMO" WindowStartupLocation="CenterScreen" Width="640" Height="480"> <WrapPanel Margin="0,0,0,0" Background="White"> <Rectangle Margin="10,10,10,10" Fill ="Azure" Width="60" Height="60"/> <Rectangle Margin="10,10,10,10" Fill ="Azure" Width="60" Height="60"/> <Rectangle Margin="10,10,10,10" Fill ="Azure" Width="60" Height="60"/> <Rectangle Margin="10,10,10,10" Fill ="Azure" Width="60" Height="60"/> <Rectangle Margin="10,10,10,10" Fill ="Azure" Width="60" Height="60"/> <Rectangle Margin="10,10,10,10" Fill ="Azure" Width="60" Height="60"/> <Rectangle Margin="10,10,10,10" Fill ="Azure" Width="60" Height="60"/> <Rectangle Margin="10,10,10,10" Fill ="Azure" Width="60" Height="60"/> <Rectangle Margin="10,10,10,10" Fill ="Azure" Width="60" Height="60"/> <Rectangle Margin="10,10,10,10" Fill ="Azure" Width="60" Height="60"/> <Rectangle Margin="10,10,10,10" Fill ="Azure" Width="60" Height="60"/> </WrapPanel> </Window> C#代码实现: namespace WPFLayoutDemo { public partial class WrapPanelDEMOCodeBehind { public WrapPanelDEMOCodeBehind() { this.InitializeComponent(); WrapPanel wp = new WrapPanel(); //把wp添加为窗体的子控件 this.Content = wp; wp.Margin = new Thickness(0, 0, 0, 0); wp.Background = new SolidColorBrush(Colors.White); //遍历增加Rectangles Rectangle r; for (int i = 0; i <= 10; i++) { r = new Rectangle(); r.Fill = new SolidColorBrush(Colors.Azure); r.Margin = new Thickness(10, 10, 10, 10); r.Width = 60; r.Height = 60; wp.Children.Add(r); } } } }   七. DockPanel   DockPanel定义一个区域,在此区域中,您可以使子元素通过描点的形式排列。停靠面板其实就是在WinForm类似于Dock属性的元素。DockPanel会对每个子元素进行排序,并停靠在面板的一侧,多个停靠在同侧的元素则按顺序排序,最后一个元素填充这个Panel(这个需要设置LastChildFill属性为 True)。对于在DockPanel中的元素的停靠属性可以通过Panel.Dock的附加属性来设置. 要实现的效果如下图(用XAML和C#实现同一效果):   XAML代码实现: <Window xmlns=" xmlns:x=" x:Class="WPFLayoutDemo.DockPanelDEMO" x:Name="Window" Title="DockPanelDEMO" WindowStartupLocation="CenterScreen" Width="640" Height="480"> <DockPanel Width="Auto" Height="Auto" LastChildFill="True"> <Rectangle Fill="Beige" Stroke="BlanchedAlmond" Height="180" DockPanel.Dock="Top"/> <Rectangle Fill="Azure" Stroke="Orange" /> </DockPanel> </Window> C#代码实现: namespace WPFLayoutDemo { public partial class DockPanelDEMOCodeBehind { public DockPanelDEMOCodeBehind() { this.InitializeComponent(); DockPanel dp = new DockPanel(); dp.LastChildFill = true; dp.Width = Double.NaN; //这个就相当于在XAML中设置Width="Auto" dp.Height = Double.NaN; //这个就相当于在XAML中设置Height="Auto" //把dp添加为窗体的子控件 this.Content = dp; //添加Rectangles Rectangle rTop = new Rectangle(); rTop.Fill = new SolidColorBrush(Colors.BlanchedAlmond); rTop.Stroke = new SolidColorBrush(Colors.BlanchedAlmond); rTop.Height = 180; dp.Children.Add(rTop); rTop.SetValue(DockPanel.DockProperty,Dock.Top); Rectangle rFill = new Rectangle(); rFill.Fill = new SolidColorBrush(Colors.Azure); rFill.Stroke = new SolidColorBrush(Colors.Azure); dp.Children.Add(rFill); } } } 八. Grid   Grid和其他各个Panel比较起来,功能最多也最为复杂,它由<Grid.ColumnDefinitions>列元素集和<Grid.RowDefinitions>行元素集合两种元素组成。而放置在Grid面板中的控件元素都必须显示采用附加属性语法定义其放置所在的行和列,否则元素均默认放置在第0行第0列。由于Grid的组成并非简单的添加属性标记来区分行列,这也使得用户在实际应用中可以具体到某一单元格中,所以布局起来就很精细了。 Grid的列宽与行高可采用固定、自动、按比列三种方式定义 <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="40" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="300" /> </Grid.ColumnDefinitions> </Grid> 第一种,固定长度——宽度不够,会裁剪,不好用。单位pixel。 第二种,自动长度——自动匹配列中最长元素的宽度。 第三种,比例长度——*表示占用剩余的全部宽度;两行都是*,将平分剩余宽度;像上面的一个2*,一个*,表示前者2/3宽度。 跨越多行和多列 <Rectangle Fill="Silver" Grid.Column="1" Grid.ColumnSpan="3"/> 使用Grid.ColumnSpan和Grid.RowSpan附加属性可以让相互间隔的行列合并,所以元素也可以跨越多个单元格。 使用GridSplit分割 <GridSplitter Height="6" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Row="2" Grid.Column="2"></GridSplitter> 使用GridSplit控件结合Grid控件实现类似于WinForm中SplitContainer的功能,这个大家在WinForm当中经常用到,我们也不多做介绍。     要实现的效果如下图(用XAML和C#实现同一效果):   XAML代码实现: <Window xmlns=" xmlns:x=" x:Class="WPFLayoutDemo.GridDEMO" x:Name="Window" Title="GridDEMO" WindowStartupLocation="CenterScreen" Width="640" Height="480"> <Grid Width="Auto" Height="Auto" > <Grid.ColumnDefinitions> <ColumnDefinition Width="139"/> <ColumnDefinition Width="184*"/> <ColumnDefinition Width="45*" /> <ColumnDefinition Width="250*"/> </Grid.ColumnDefinitions> <Rectangle Fill="Azure" Grid.ColumnSpan="2" Margin="0,0,21,0" /> <Rectangle Fill="Silver" Grid.Column="1" Grid.ColumnSpan="3"/> </Grid> </Window> C#代码实现: namespace WPFLayoutDemo { public partial class GridDEMOCodeBehind { public GridDEMOCodeBehind() { this.InitializeComponent(); Grid grid = new Grid(); grid.Width = Double.NaN; //这个就相当于在XAML中设置Width="Auto" grid.Height = Double.NaN; //这个就相当于在XAML中设置Height="Auto" //把grid添加为窗体的子控件 this.Content = grid; //列一 ColumnDefinition cd1 = new ColumnDefinition(); cd1.Width = new GridLength(139); grid.ColumnDefinitions.Add(cd1); //列二 ColumnDefinition cd2 = new ColumnDefinition(); cd2.Width = new GridLength(1, GridUnitType.Star); grid.ColumnDefinitions.Add(cd2); //列三 ColumnDefinition cd3 = new ColumnDefinition(); cd3.Width = new GridLength(2, GridUnitType.Star); grid.ColumnDefinitions.Add(cd3); //把单元格添加到grid中 Rectangle r1c1 = new Rectangle(); r1c1.Fill = new SolidColorBrush(Colors.Azure); r1c1.SetValue(Grid.ColumnProperty, 0); r1c1.SetValue(Grid.RowProperty, 0); grid.Children.Add(r1c1); Rectangle r1c23 = new Rectangle(); r1c23.Fill = new SolidColorBrush(Colors.Silver); r1c23.SetValue(Grid.ColumnProperty, 1); r1c23.SetValue(Grid.ColumnSpanProperty, 2); grid.Children.Add(r1c23); } } } 九 UniformGrid   介绍了前面的Grid,接下来的这个UniformGrid 就太简单了,均布网格的是Grid的简化版本,每个单元格的大小相同,不用在定义行列集合。均布网格每个单元格只能容纳一个元素,将自动按照定义在其内部的元素个数,自动创建行列,并通常保持相同的行列数。 要实现的效果如下图(用XAML和C#实现同一效果):   XAML代码实现: <Window x:Class="WPFLayoutDemo.UniformGridDEMO" xmlns=" xmlns:x=" Title="UniformGridDEMO" Height="300" Width="300"> <UniformGrid Columns="2" Rows="2" Name="uniformGrid1" > <Rectangle Margin="10,10,10,10" Fill ="Gray"/> <Rectangle Margin="10,10,10,10" Fill ="Gray" /> <Rectangle Margin="10,10,10,10" Fill ="Gray" /> <Rectangle Margin="10,10,10,10" Fill ="Gray" /> </UniformGrid> </Window> C#代码实现: namespace WPFLayoutDemo { public partial class UniformGridDEMOCodeBehind : Window { public UniformGridDEMOCodeBehind() { InitializeComponent(); UniformGrid wp = new UniformGrid(); //把wp添加为窗体的子控件 this.Content = wp; wp.Margin = new Thickness(0, 0, 0, 0); wp.Background = new SolidColorBrush(Colors.White); //遍历增加Rectangles Rectangle r; for (int i = 0; i <= 10; i++) { r = new Rectangle(); r.Fill = new SolidColorBrush(Colors.Gray); r.Margin = new Thickness(10, 10, 10, 10); wp.Children.Add(r);
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传
相似文档                                   自信AI助手自信AI助手

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服