WPF布局
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
这篇文章主要是对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.自定义布局控件
<RectangleFill="Red"
Stroke="Azure"
Width="209"
Height="159"
Canvas.Left="310"Canvas.Top="181"/>
<EllipseFill="Azure"
Stroke="Green"
Width="258"Height="97"
Panel.ZIndex="1"
要实现的效果如下图(用XAML和C#实现同一效果):
XAML代码实现:
<Window
xmlns="/winfx/2006/xaml/presentation"
xmlns:x="/winfx/2006/xaml"
{
this.InitializeComponent();
Canvascanv =newCanvas();
//把canv添加为窗体的子控件
this.Content = canv;
canv.Margin =newThickness(0, 0, 0, 0);
canv.Background =newSolidColorBrush(Colors.White);
· 15.本文总结
· 16.系列进度
· 17.相关代码
WPF的布局控件都在System.Windows.Controls.Panel这个基类下面,使用Panel元素在WPF应用程序中放置和排列子对象。它具体包括哪些布局控件以及如何使用这些布局控件(分别用XAML和C#两种方式实现同一个功能)、如何开发自定义的布局控件,也就是本文所要讨论的范畴:
x:Class="WPFLayoutDemo.CanvasDEMO"
x:Name="Window"
Title="CanvasDEMO"
WindowStartupLocation="CenterScreen"
Width="640"Height="480">
<CanvasMargin="0,0,0,0"Background="White">
r.SetValue(Canvas.TopProperty, (double)122);
canv.Children.Add(r);
//Ellipse
Ellipseel =newEllipse();
el.Fill =newSolidColorBrush(Colors.Azure);
el.Stroke =newSolidColorBrush(Colors.Azure);
要实现的效果如下图(用XAML和C#实现同一效果):
XAML代码实现:
<Window
xmlns="/winfx/2006/xaml/presentation"
xmlns:x="/winfx/2006/xaml"
要实现的效果如下图(用XAML和C#实现同一效果):
XAML代码实现:
<Window
xmlns="/winfx/2006/xaml/presentation"
xmlns:x="/winfx/2006/xaml"
布局系统为Children集合的每个成员完成两个处理过程:测量处理过程(Measure)和排列处理过程(Arrange)。每个子Panel均提供自己的MeasureOverride和ArrangeOverride方法,以实现自己特定的布局行为。
Canvas比较简单,只是一个存储元素的容器,它不会自动调整内部元素的排列及大小。不指定元素位置,元素将默认显示在画布的左上方。Canvas的主要用途是用来画图。Canvas默认不会自动裁减超过自身范围的内容,即溢出的内容会显示在Canvas外面,这是因为默认ClipToBounds="False";我们可以通过设置ClipToBounds="True来裁剪多出的内容。
Canvas.Left="165"Canvas.Top="145"/>
</Canvas>
</Window>
C#代码实现:
namespaceWPFLayoutDemo
{
public partial classCanvasDEMOCodeBehind
{
publicCanvasDEMOCodeBehind()
b1.Content ="Top of Stack";
sp.Children.Add(b1);
//Button2
Buttonb2 =newButton();
b2.Content ="Middle of Stack";
sp.Children.Add(b2);
//Button3
Buttonb3 =newButton();
b3.Content ="Bottom of Stack";
sp.Children.Add(b3);
}
}
}
WrapPanel是一个非常简单的面板,从左至右按顺序位置定位子元素,如果排满断开至下一行。后续排序按照从上至下或从右至左的顺序进行。WrapPanel面板也提供了Orientation属性设置排列方式,这跟上面的StackPanel基本相似。不同的是WrapPanel会根据内容自动换行。
一个Panel的呈现是测量和排列Children子元素、然后在屏幕上绘制它们的过程。所以在布局的过程中会经过一系列的计算,那么Children越多,执行的计算次数就越多。如果不需要较为复杂的Panel(如Grid和自定义复杂的Panel),则可以使用构造相对简单的布局(如Canvas、UniformGrid等),这种布局可带来更好的性能。如果有可能,我们应尽量避免不必要地调用UpdateLayout方法。
//Rectangle
Rectangler =newRectangle();
r.Fill =newSolidColorBrush(Colors.Red);
r.Stroke =newSolidColorBrush(Colors.Red);
r.Width = 145;
r.Height = 126;
r.SetValue(Canvas.LeftProperty, (double)124);
{
public partial classStackPanelDEMOCodeBehind
{
publicStackPanelDEMOCodeBehind()
{
this.InitializeComponent();
StackPanelsp =newStackPanel();
//把sp添加为窗体的子控件
x:Class="WPFLayoutDemo.StackPanelDEMO"
x:Name="Window"
Title="StackPanelDEMO"
WindowStartupLocation="CenterScreen"
Width="640"Height="480">
<StackPanelMargin="0,0,0,0"Background="White"Orientation="Vertical">
<RectangleMargin="10,10,10,10"Fill="Azure"Width="60"Height="60"/>
canv.Children.Add(el);
}ห้องสมุดไป่ตู้
}
}
StackPanel就是将子元素按照堆栈的形式一一排列,通过设置面板的Orientation属性设置了两种排列方式:横排(Horizontal默认的)和竖排(Vertical)。纵向的StackPanel默认每个元素宽度与面板一样宽,反之横向亦然。如果包含的元素超过了面板空间,它只会截断多出的内容。元素的Margin属性用于使元素之间产生一定得间隔,当元素空间大于其内容的空间时,剩余空间将由HorizontalAlignment和VerticalAlignment属性来决定如何分配。其他属性,大家可以看看如下类图:
Panel具体继承关系详见下面类图:
如上图,公共属性太多了,就简单介绍几个常见的属性:Margin是元素与其他元素的外边距;Padding是指在本元素内部的元素内容与边缘的距离;前面这两个元素基本和ASP.NE中的Margin和Padding类似,只是定义大小的设置不同而已;FlowDirection属性标示元素的内容显示方向;Panel.ZIndex是相对于显示屏的Z轴坐标,用于调整层叠元素的显示先后;RenderTransform和LayoutTransform用来将缩放和旋转的变换应用到某个元素上。
<ButtonContent="Top of Stack"/>
<ButtonContent="Middle of Stack"/>
<ButtonContent="Bottom Of Stack"/>
</StackPanel>
</Window>
C#代码实现:
namespaceWPFLayoutDemo
每当Panel内的子元素改变其位置时,布局系统就可能触发一个新的处理过程。对此,了解哪些事件会调用布局系统就很重要,因为不必要的调用可能导致应用程序性能变差。
换句话说,布局是一个递归系统,实现在屏幕上对元素进行大小调整、定位和绘制,然后进行呈现。具体如下图,要实现控件0的布局,那么先要实现0的子控件01,02...的布局,要实现01的布局,那么得实现01的子控件001,002...的布局,如此循环直到子控件的布局完成后,再完成父控件的布局,最后递归回去直到递归结束,这样整个布局过程就完成了.
el.Width = 121;
el.Height = 100;
el.SetValue(Canvas.ZIndexProperty, 1);
el.SetValue(Canvas.LeftProperty, (double)195);
el.SetValue(Canvas.TopProperty, (double)191);
this.Content = sp;
sp.Margin =newThickness(0, 0, 0, 0);
sp.Background =newSolidColorBrush(Colors.White);
sp.Orientation =Orientation.Vertical;
//Button1
Buttonb1 =newButton();
x:Class="WPFLayoutDemo.WrapPanelDEMO"
x:Name="Window"
Title="WrapPanelDEMO"
WindowStartupLocation="CenterScreen"
Width="640"Height="480">
<WrapPanelMargin="0,0,0,0"Background="White">
首先很高兴这个系列能得到大家的关注和支持,这段时间一直在研究Windows Azure,所以暂缓了更新,同时也本着想把它写好、宁缺毋滥的精神,在速度上自然也就慢了下来,这篇文章拖拖拉拉也经历了十多天才发布出来(每天写一点),不过请大家放心,这个系列一定会继续写下去。由于自己才疏学浅且是对这些技术的使用总结和心得体会,错误之处在所难免,怀着技术交流的心态,在这里发表出来,所以希望大家能够多多指点,这样在使一部分人受益的同时也能纠正我的错误观点,以便和各位共同提高。
· 1.摘要
· 2.本文提纲
· 3.总体介绍
· 4.Canvas
· 5.StackPanel
· 6.WrapPanel
· 7.DockPanel
· 8.Grid
· 9.UniformGrid
· 10.ViewBox
· 11.Border
· 12.ScrollViewer
· 13.布局综合应用
· 14.自定义布局控件
<RectangleFill="Red"
Stroke="Azure"
Width="209"
Height="159"
Canvas.Left="310"Canvas.Top="181"/>
<EllipseFill="Azure"
Stroke="Green"
Width="258"Height="97"
Panel.ZIndex="1"
要实现的效果如下图(用XAML和C#实现同一效果):
XAML代码实现:
<Window
xmlns="/winfx/2006/xaml/presentation"
xmlns:x="/winfx/2006/xaml"
{
this.InitializeComponent();
Canvascanv =newCanvas();
//把canv添加为窗体的子控件
this.Content = canv;
canv.Margin =newThickness(0, 0, 0, 0);
canv.Background =newSolidColorBrush(Colors.White);
· 15.本文总结
· 16.系列进度
· 17.相关代码
WPF的布局控件都在System.Windows.Controls.Panel这个基类下面,使用Panel元素在WPF应用程序中放置和排列子对象。它具体包括哪些布局控件以及如何使用这些布局控件(分别用XAML和C#两种方式实现同一个功能)、如何开发自定义的布局控件,也就是本文所要讨论的范畴:
x:Class="WPFLayoutDemo.CanvasDEMO"
x:Name="Window"
Title="CanvasDEMO"
WindowStartupLocation="CenterScreen"
Width="640"Height="480">
<CanvasMargin="0,0,0,0"Background="White">
r.SetValue(Canvas.TopProperty, (double)122);
canv.Children.Add(r);
//Ellipse
Ellipseel =newEllipse();
el.Fill =newSolidColorBrush(Colors.Azure);
el.Stroke =newSolidColorBrush(Colors.Azure);
要实现的效果如下图(用XAML和C#实现同一效果):
XAML代码实现:
<Window
xmlns="/winfx/2006/xaml/presentation"
xmlns:x="/winfx/2006/xaml"
要实现的效果如下图(用XAML和C#实现同一效果):
XAML代码实现:
<Window
xmlns="/winfx/2006/xaml/presentation"
xmlns:x="/winfx/2006/xaml"
布局系统为Children集合的每个成员完成两个处理过程:测量处理过程(Measure)和排列处理过程(Arrange)。每个子Panel均提供自己的MeasureOverride和ArrangeOverride方法,以实现自己特定的布局行为。
Canvas比较简单,只是一个存储元素的容器,它不会自动调整内部元素的排列及大小。不指定元素位置,元素将默认显示在画布的左上方。Canvas的主要用途是用来画图。Canvas默认不会自动裁减超过自身范围的内容,即溢出的内容会显示在Canvas外面,这是因为默认ClipToBounds="False";我们可以通过设置ClipToBounds="True来裁剪多出的内容。
Canvas.Left="165"Canvas.Top="145"/>
</Canvas>
</Window>
C#代码实现:
namespaceWPFLayoutDemo
{
public partial classCanvasDEMOCodeBehind
{
publicCanvasDEMOCodeBehind()
b1.Content ="Top of Stack";
sp.Children.Add(b1);
//Button2
Buttonb2 =newButton();
b2.Content ="Middle of Stack";
sp.Children.Add(b2);
//Button3
Buttonb3 =newButton();
b3.Content ="Bottom of Stack";
sp.Children.Add(b3);
}
}
}
WrapPanel是一个非常简单的面板,从左至右按顺序位置定位子元素,如果排满断开至下一行。后续排序按照从上至下或从右至左的顺序进行。WrapPanel面板也提供了Orientation属性设置排列方式,这跟上面的StackPanel基本相似。不同的是WrapPanel会根据内容自动换行。
一个Panel的呈现是测量和排列Children子元素、然后在屏幕上绘制它们的过程。所以在布局的过程中会经过一系列的计算,那么Children越多,执行的计算次数就越多。如果不需要较为复杂的Panel(如Grid和自定义复杂的Panel),则可以使用构造相对简单的布局(如Canvas、UniformGrid等),这种布局可带来更好的性能。如果有可能,我们应尽量避免不必要地调用UpdateLayout方法。
//Rectangle
Rectangler =newRectangle();
r.Fill =newSolidColorBrush(Colors.Red);
r.Stroke =newSolidColorBrush(Colors.Red);
r.Width = 145;
r.Height = 126;
r.SetValue(Canvas.LeftProperty, (double)124);
{
public partial classStackPanelDEMOCodeBehind
{
publicStackPanelDEMOCodeBehind()
{
this.InitializeComponent();
StackPanelsp =newStackPanel();
//把sp添加为窗体的子控件
x:Class="WPFLayoutDemo.StackPanelDEMO"
x:Name="Window"
Title="StackPanelDEMO"
WindowStartupLocation="CenterScreen"
Width="640"Height="480">
<StackPanelMargin="0,0,0,0"Background="White"Orientation="Vertical">
<RectangleMargin="10,10,10,10"Fill="Azure"Width="60"Height="60"/>
canv.Children.Add(el);
}ห้องสมุดไป่ตู้
}
}
StackPanel就是将子元素按照堆栈的形式一一排列,通过设置面板的Orientation属性设置了两种排列方式:横排(Horizontal默认的)和竖排(Vertical)。纵向的StackPanel默认每个元素宽度与面板一样宽,反之横向亦然。如果包含的元素超过了面板空间,它只会截断多出的内容。元素的Margin属性用于使元素之间产生一定得间隔,当元素空间大于其内容的空间时,剩余空间将由HorizontalAlignment和VerticalAlignment属性来决定如何分配。其他属性,大家可以看看如下类图:
Panel具体继承关系详见下面类图:
如上图,公共属性太多了,就简单介绍几个常见的属性:Margin是元素与其他元素的外边距;Padding是指在本元素内部的元素内容与边缘的距离;前面这两个元素基本和ASP.NE中的Margin和Padding类似,只是定义大小的设置不同而已;FlowDirection属性标示元素的内容显示方向;Panel.ZIndex是相对于显示屏的Z轴坐标,用于调整层叠元素的显示先后;RenderTransform和LayoutTransform用来将缩放和旋转的变换应用到某个元素上。
<ButtonContent="Top of Stack"/>
<ButtonContent="Middle of Stack"/>
<ButtonContent="Bottom Of Stack"/>
</StackPanel>
</Window>
C#代码实现:
namespaceWPFLayoutDemo
每当Panel内的子元素改变其位置时,布局系统就可能触发一个新的处理过程。对此,了解哪些事件会调用布局系统就很重要,因为不必要的调用可能导致应用程序性能变差。
换句话说,布局是一个递归系统,实现在屏幕上对元素进行大小调整、定位和绘制,然后进行呈现。具体如下图,要实现控件0的布局,那么先要实现0的子控件01,02...的布局,要实现01的布局,那么得实现01的子控件001,002...的布局,如此循环直到子控件的布局完成后,再完成父控件的布局,最后递归回去直到递归结束,这样整个布局过程就完成了.
el.Width = 121;
el.Height = 100;
el.SetValue(Canvas.ZIndexProperty, 1);
el.SetValue(Canvas.LeftProperty, (double)195);
el.SetValue(Canvas.TopProperty, (double)191);
this.Content = sp;
sp.Margin =newThickness(0, 0, 0, 0);
sp.Background =newSolidColorBrush(Colors.White);
sp.Orientation =Orientation.Vertical;
//Button1
Buttonb1 =newButton();
x:Class="WPFLayoutDemo.WrapPanelDEMO"
x:Name="Window"
Title="WrapPanelDEMO"
WindowStartupLocation="CenterScreen"
Width="640"Height="480">
<WrapPanelMargin="0,0,0,0"Background="White">
首先很高兴这个系列能得到大家的关注和支持,这段时间一直在研究Windows Azure,所以暂缓了更新,同时也本着想把它写好、宁缺毋滥的精神,在速度上自然也就慢了下来,这篇文章拖拖拉拉也经历了十多天才发布出来(每天写一点),不过请大家放心,这个系列一定会继续写下去。由于自己才疏学浅且是对这些技术的使用总结和心得体会,错误之处在所难免,怀着技术交流的心态,在这里发表出来,所以希望大家能够多多指点,这样在使一部分人受益的同时也能纠正我的错误观点,以便和各位共同提高。