您的位置:首页 > 其它

Silverlight学习笔记(3):Silverlight的界面布局

2010-10-11 22:01 435 查看
在上一篇中讲述了使用VS2010开发Silverlight的一些基础知识,并且讲述了Silverlight的部署和代码安全知识,这一篇主要是讲述如何在Silverlight中摆放界面元素。
记得早年前我还在学习Java的时候,当时有两种开发Java SE的方法,一种是使用JCreator或者JBuilder之类的IDE开发(现在这二者都几乎没人用了,流行的是Eclipse或者NetBeans);一种是使用Visual J++开发。使用前一种方法开发的Java程序可以多种操作系统平台上运行,不过界面布局比较麻烦,什么CardLayout、FlowLayout、BorderLayout、GridBagLayout、GridLayout等等,开发一个复杂的界面需要开发人员对各种布局类都有所了解;使用Visual J++开发的话可以使用XY坐标来定位元素,相对来说容易多了,不过这种开发的Java软件并不是严格意义上的Java软件,它只能在Windows平台上运行。Java从出现到现在,在Java EE和Java ME上都相对比较成功,而唯独在Java SE上表现不佳,不知道跟它难以使用的界面布局有关系。
布局概述
在上一篇提到了XAML语言,它适用于在WPF和Silverlight中进行界面布局的标记语言,它是一种有特定要求的XML语言,从某种意义上来说,我觉得它和XHTML走得更近一些:首先它们都是有特定格式的XML语言,其次它们都是用于界面布局。除此之外,在XAML语言中还有一个特点,那就是每一个元素都代表着一个Silverlight中的类,并且在XAML中只能有一个顶级元素。因此在进行WPF和Silverlight开发时不能绕开的一个问题就是界面布局,在Silverlight中常见的界面布局类有Canvas、Grid和StackPanel。
Canvas、Grid和StackPanel其实都是继承自System.Windows.Controls.Panel的类,它们的继承层次关系如下图:



Panel类有如下比较常见的属性:
Background:用于填充 Panel 的边框之间的区域的 Brush。
Children:此 Panel 的子元素的 UIElementCollection。
Height:元素的建议高度。
HorizontalAlignment:在父元素(如面板或项控件)中构成此元素时应用于此元素的水平对齐特征。
MaxHeight:元素的最大高度约束,MaxHeight的默认值是PositiveInfinity(正无穷大)。
MaxWidth:元素的最大宽度约束,MaxWidth的默认值是PositiveInfinity(正无穷大)。
MinHeight:元素的最小高度约束,MinHeight的默认值分别是Auto(自动调整)。
MinWidth:元素的最小宽度约束,MinWidth的默认值分别是Auto(自动调整)。
VerticalAlignment:在父元素(如面板或项控件)中组合此元素时应用于此元素的垂直对齐特征。
Width:元素的宽度。
可以看出在这里存在着Height、MaxHeigh、MinHeight及Width、MaxWidth、MinWidth这么两组与高度和宽度相关的属性,这的确让初学的人有些模糊。这些值之间存在着什么样的关系呢?拿Width、MaxWidth、MinWidth来说,它们存在的关系如下:如果这三个值之间存在冲突,则应用程序确定宽度的实际顺序是:首先必须采用 MinWidth;然后采用 MaxWidth;最后,如果这些值中的每个值都在限制之内,则采用 Width。为什么对于Width或者Height会出现这么三个属性呢?这是跟编程有一定的关系,假如我们在一个布局容器中水平放置了三个按钮,每个按钮的宽度是60像素,即使不考虑这三个按钮之间的间隙显示这三个按钮的宽度至少需要180像素,在默认情况下Width、MaxWidth、MinWidth的默认值分别是Auto(自动调整)、PositiveInfinity(正无穷大)、0.0,这样一来按照上面的规则会采取自动调整的方式。
StackPanel布局用法
StackPane是上面提到的几种布局中最简单的一种布局方式,它在一行或者一列中显示所有的子控件,默认情况下它是在一列中显示所有元素的,不过可以通过设置它的Orientation 属性为Horizontal以指示在一行中显示所有元素。
下面是一个使用StackPanel的简单例子:

<navigation:Page x:Class="SilverlightDemo1.StackPanelDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="640" d:DesignHeight="480"
Title="StackPanelDemo Page">
<StackPanel Height="100" Name="stackPanel1" Width="200" Background="Yellow">
<Button Content="按钮一" Height="23" Name="button1" Width="100" />
<Button Content="按钮二" Height="23" Name="button2" Width="200" />
<Button Content="按钮三" Height="23" Name="button3" Width="400" />
</StackPanel>
</navigation:Page>
这个Page的显示效果如下:



在上面的代码中我们设置StackPanel的Width为200,没有设置MaxWidth、MinWidth的值,最终实际显示宽度为200,因为此时MaxWidth和MinWidth都采用了默认值,因为这这三个值有冲突但是都在限制(没有找到具体对限制的定义,周公推测为MinWidth≤Width≤MaxWidth,如果您觉得周公的推测不正确,请告知以免误导大家,谢谢)之内,所以最终实际宽度为200。
如果设置StackPanel的Width、MaxWidth、MinWidth分别为200、400、100,最终实际显示宽度仍为200,原因同上,如下图所示:



如果设置StackPanel的Width、MaxWidth、MinWidth分别为200、100、100,最终实际显示宽度为100,这里MaxWidth和MinWidth都是100,而Width却是200不在限制之内,所以最终显示宽度为MinWidth设置的宽度,如下图所示:



如果设置StackPanel的Width、MaxWidth、MinWidth分别为200、400、500,最终实际显示宽度为500,这里MaxWidth和MinWidth分别是400和500,而Width却是200不在限制之内,所以最终显示宽度也为MinWidth设置的宽度,如下图所示:

Grid布局用法
Grid布局是Silverlight一种比较复杂的布局,它有点像我们HTML中的Table元素,将空间划分为行和列组成的单元格,在每个单元格中可以放置其它元素,下面是一个使用Grid的例子:

<navigation:Page x:Class="SilverlightDemo1.GridDemo1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="400" d:DesignHeight="300"
Title="GridDemo1 Page">
<Grid x:Name="LayoutRoot" Background="Pink">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="200" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Content="按钮一" Height="23" HorizontalAlignment="Left" Name="button1" VerticalAlignment="Center" Width="75" Grid.Column="0" Grid.Row="0" />
<Button Content="按钮二" Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Center" Name="button2" VerticalAlignment="Top" Width="75" />
<TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Center" Name="textBox1" VerticalAlignment="Center" Width="80" Text="文本框" />
</Grid>
</navigation:Page>
它的显示效果如下:



当然Grid也可以像HTML中的Table一样跨行或者跨列,这需要通过设置控件的RowSpan或者ColumnSpan属性,下面就是一个例子:

<navigation:Page x:Class="SilverlightDemo1.GridDemo1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="400" d:DesignHeight="300"
Title="GridDemo1 Page">
<Grid x:Name="LayoutRoot" Background="Pink">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="200" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Content="按钮一" Height="220" HorizontalAlignment="Left" Name="button1" Width="75" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" />
<Button Content="按钮二" Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Center" Name="button2" VerticalAlignment="Top" Width="75" />
<TextBox Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2" Height="23" Name="textBox1" VerticalAlignment="Center" Width="80" Text="文本框" />
<Button Content="按钮三" Grid.Column="2" Height="23" HorizontalAlignment="Left" Name="button3" VerticalAlignment="Top" Width="75" />
<Button Content="按钮四" Grid.Column="3" Grid.Row="1" Height="23" HorizontalAlignment="Left" Name="button4" VerticalAlignment="Top" Width="75" />
</Grid>
</navigation:Page>
它的显示效果如下:



Canvas布局用法
相比Grid和Grid的布局方式来说,Canvas提供了另外一种途径来布置我们的控件,它采用了我们比较熟悉的利用坐标的方式的,在使用Canvas布局时可以设置每个控件Top和Left属性,也就是设置控件距离它所在的容器的距离,下面就是一个例子:

<navigation:Page x:Class="SilverlightDemo1.CanvasDemo1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="640" d:DesignHeight="480"
Title="CanvasDemo1 Page">
<Canvas Height="240" Name="canvas1" Width="300" Background="Teal">
<Button Canvas.Left="40" Canvas.Top="161" Content="登录" Height="23" Name="button1" Width="75" />
<TextBlock Canvas.Left="40" Canvas.Top="56" Height="23" Name="textBlock1" Text="用户名" />
<TextBlock Canvas.Left="40" Canvas.Top="102" Height="23" Name="textBlock2" Text="密码" />
<Button Canvas.Left="183" Canvas.Top="161" Content="取消" Height="23" Name="button2" Width="75" />
<TextBox Canvas.Left="138" Canvas.Top="56" Height="23" Name="textBox1" Width="120" />
<PasswordBox Canvas.Left="138" Canvas.Top="102" Height="23" Name="passwordBox1" Width="120" />
</Canvas>
</navigation:Page>
它的显示效果如下:



在代码中我们对用户名所对应的文本框的设置是:

<TextBox Canvas.Left="138" Canvas.Top="56" Height="23" Name="textBox1" Width="120" />
于是就会在距离Canvas顶部56、左边138处显示一个高度为23、宽度为120的文本框。
布局的综合使用
虽然在XAML中只能有一个顶级元素,但是这并不意味着在一个界面中只使用一种界面布局,我们完全可以在外层布局中嵌套内层布局,就像我们在HTML的Table中再次嵌套Table一样,下面是一个简单的例子:

<navigation:Page x:Class="SilverlightDemo1.Graphics"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="800" d:DesignHeight="600"
Title="Chapter10 Page">
<StackPanel Width="800" Height="600" Orientation="Vertical">
<Canvas Width="800" Height="200" Background="White">
<Canvas.Resources>
<Storyboard x:Name="myStroryboard">
<DoubleAnimation Storyboard.TargetName="myTransform" Storyboard.TargetProperty="Angle"
From="0" To="360" Duration="0:0:5" RepeatBehavior="Forever"/>
</Storyboard>
</Canvas.Resources>
<Image Canvas.Left="50" Canvas.Top="50" Height="100" Name="image01" Stretch="Fill" Width="100" Source="image/15.jpg" MouseEnter="Image_MouseEnter" MouseLeave="Image_MouseLeave">
<Image.RenderTransform>
<RotateTransform x:Name="myTransform" Angle="15" CenterX="50" CenterY="50"></RotateTransform>
</Image.RenderTransform>
</Image>
<Image Canvas.Left="350" Canvas.Top="0" Height="100" Name="image02" Stretch="Fill" Width="100" Source="image/15.jpg">
</Image>
<Image Canvas.Left="350" Canvas.Top="0" Height="100" Name="image03" Stretch="Fill" Width="100" Source="image/15.jpg" Opacity="0.8">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="-0.75"></ScaleTransform>
<TranslateTransform Y="180" X="30"></TranslateTransform>
<SkewTransform AngleX="-15"></SkewTransform>
</TransformGroup>
</Image.RenderTransform>
<Image.OpacityMask>
<LinearGradientBrush StartPoint="0.5,0.0" EndPoint="0.5,1.0">
<GradientStop Offset="0.0" Color="#00000000"></GradientStop>
<GradientStop Offset="1.0" Color="#FF000000"></GradientStop>
</LinearGradientBrush>
</Image.OpacityMask>
</Image>
</Canvas>
<Canvas Width="800" Height="200">
<Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image31" Stretch="Fill" Width="200" Source="image/14.jpg" />
<Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image32" Stretch="Fill" Width="200" Source="image/14.jpg">
<Image.RenderTransform>
<RotateTransform Angle="15" CenterX="0" CenterY="0"></RotateTransform>
</Image.RenderTransform>
</Image>
<Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image33" Stretch="Fill" Width="200" Source="image/14.jpg">
<Image.RenderTransform>
<RotateTransform Angle="30" CenterX="50" CenterY="300"></RotateTransform>
</Image.RenderTransform>
</Image>
<Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image34" Stretch="Fill" Width="200" Source="image/14.jpg">
<Image.RenderTransform>
<RotateTransform Angle="45" CenterX="0" CenterY="50"></RotateTransform>
</Image.RenderTransform>
</Image>
</Canvas>
<Canvas Width="800" Height="200">
<Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image1" Stretch="Fill" Width="200" Source="image/14.jpg" />
<Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image2" Stretch="Fill" Width="200" Source="image/14.jpg">
<Image.RenderTransform>
<RotateTransform Angle="15"></RotateTransform>
</Image.RenderTransform>
</Image>
<Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image3" Stretch="Fill" Width="200" Source="image/14.jpg">
<Image.RenderTransform>
<RotateTransform Angle="30"></RotateTransform>
</Image.RenderTransform>
</Image>
<Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image4" Stretch="Fill" Width="200" Source="image/14.jpg">
<Image.RenderTransform>
<RotateTransform Angle="40"></RotateTransform>
</Image.RenderTransform>
</Image>
</Canvas>
</StackPanel>
</navigation:Page>
它的显示效果如下:



总结:本篇主要讲述了Silverlight中几种常见的布局:StackPanel可以将控件按行或者按列布局,这是一种比较简单的布局方式;Grid可以采用类似于HTML中Table的方式布局,并且可以设置控件跨行或者跨列摆放;Canvas控件采用类似于坐标定位的方式对控件进行布局。还有一些布局在本篇中没有讲述,读者朋友可以在学习时借鉴这些知识来学习,其实利用这些布局已经足够实现复杂的界面了。
下一篇将讲述常用控件的学习。
周公(zhoufoxcn)
2010-10-11本文出自 “周公(周金桥)的专栏” 博客,请务必保留此出处http://zhoufoxcn.blog.51cto.com/792419/404352
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: