原文地址:框架
系列地址:http://channel9.msdn.com/Series/Windows-Phone-8-Development-for-Absolute-Beginners布局
源代码: http://aka.ms/absbeginnerdevwp8
PDF版本: http://aka.ms/absbeginnerdevwp8pdf学习
我将在本课中讨论布局,换句话说如何在应用程序的用户界面上定位或者排列控件。spa
本课的计划是:3d
缺省的Windows Phone页面模板建立了一个称为"ContentPanel"的<Grid>元素。视频
该Grid元素用于其余控件的布局。它容许您定义行和列,而后每一个控件能够请求被放置在哪一行及哪一列中。对象
缺省的Windows Phone页面模板建立了一个称为"ContentPanel"的<Grid>元素。blog
在默认的MainPage.xaml页面模板中,在开始和结束标记<Grid></Grid>之间,Grid显示为空,它彷佛没有行或列的定义。然而即便他们未被显式定义,默认状况下始终有一个行定义和列定义。他们占据全部可用的垂直和水平空间以表明Grid中一个大的“单元”。任何放置在开始和结束<Grid></Grid>元素之间的项目被认为位于这个隐式的“单元”之中。生命周期
"LayoutRoot" 网格是一个定义了行的Grid。该Grid定义了两行:
请注意含有项目和页面标题的StackPanel将本身放置在第一行中,该StackPanel有一个称为Grid.Row=”0”的属性。您使用从零开始的编号方案引用行和列。
注意经过设置属性Grid.Row=”1”,内容面板网格 (ContentPanel Grid)将本身放置在第二行。
第一行将高度设置为”自动(Auto)”。第二行(行1)设置为"*"。有三种语法用来帮助设置行和列的大小。对于XAML布局,高度和宽度是相对的,并受许多因素的影响。布局引擎考虑全部这些因素以肯定在页面上项目的实际位置。
例如,“自动”表示该行的高度足以容纳放置在其中的全部控件。若是最高的控件高度是150像素,那么这就是该行的实际高度。若是它只有100像素,那么那就是该行的高度。所以“自动”表示高度是相对行内部的控件。
星号称为“比例缩放”,它表示该行的高度应该占据全部其他可用的高度。
这里是另外一种使用“比例缩放”的简单示例。我建立了一个项目,在内容面板中有针对三行的定义。请注意每一行的高度:
在星号前加上数字的含义是 “对于全部可用的空间,给我余下的1份、2份或3份”。由于全部这些行加起来的总和是6,每一个1*至关于可用高度的1/6。所以3*将得到可用高度的一半,如本示例输出所示:
除了自动和比例缩放,您还能够经过像素指定宽度和高度(以及边距)。事实上,当仅给出数字时,它表示像素的值。一般在布局中使用精确的像素并非个好主意,由于即使是Windows Phone的屏幕也可能有不一样的尺寸。相反,对于布局最好使用像自动和比例缩放这样的相对值。
在本示例中(以及原来的PetSounds示例)须要注意的一件事是除非另有指定,控件的宽度和高度都假定为100%。这就是为何矩形占据整个“单元格”的缘由。这就是为何按钮首先占据整个内容面板网格,以及为何我要指定按钮为200 x200像素的缘由。
我还想指出的是Grid能够包含一组有关列的定义(ColumnDefinitions),您能够在我建立的名称为GridsRowsAndColumns的应用程序中找到它们。这里咱们有了一个3 x 3的网格:
结果是一个简单的网格,而且在每一个“单元格”中含有一个数字。
对于本示例我但愿您注意到的另外一件事情是当未指定Grid.Row 或Grid.Column时,它将位于第一行(行0)或第一列(列0)。依靠默认设置可让您的代码更简洁。
这里有另外一个称为AlignmentAndMargins的示例应用程序。XAML以下所示:
产生这样的结果:
若是您盯着它看一下子,示例的大部份内容是显而易见的,可是有几个与对齐和边距有关的细微区别。首先,它指出VerticalAlignment和HorizontalAlignment是如何工做的(即便在给定Grid的一个单元格中,对于StackPanel一样适用)。___Alignment属性将控件拉到它们的边界。相反,边界属性将控件推离它们的边界。第二个须要观察的地方是定义边距的奇怪方式:一系列由逗号分隔的数字。这个约定从级联样式表借用而来。这些数字表明从左侧开始顺时针方向的边距像素值。所以,
Margin="10,20,30,40"
表示距左边界10个像素,顶部边界20个像素,右边界30个像素,底部边界40个像素。在这种状况下,边界针对一个单独的Grid单元格。(由于内容面板没有定义任何其余的行定义RowDefinitions和列定义ColumnDefinitions)
刚才我说过使用自动和比例缩放(*)等相对大小来定义高度和宽度一般更好。那么为何边距要使用像素来定义?边距用精确的像素表示是由于它们一般只是提供两个使用相对值对象之间的间距和填充的小数值,所以边距能够是一个固定值而不影响总体页面的布局。
StackPanel是布局的另外一种形式。它以从上到下流动的方式排列控件。
在PetSounds项目中,咱们定义了如下StackPanel,它用于在MainPage.xaml的顶部建立应用程序标题和页面标题。
两个TextBlock元素占据父元素(LayoutRoot Grid)的整个水平宽度,所以它们被以垂直方式堆叠。让咱们将ContentPanel:
从Grid转换为StackPanel:
起初这种转换只将Meow按钮垂直向下移动:
可是若是将Width和HorizontalAlignment属性从Quack按钮删除(我还删除了Button.Background属性):
而且注释掉Meow按钮的Width 和HorizontalAlignment属性,而且在MainPage()构造函数中注释掉Margin:
而后您能够看到两个按钮将以垂直方式在StackPanel中堆叠:
因此正如您所看到的,经过四件事情的联合使用,您能够实现任意想象的布局
这就是XAML布局的简单介绍。让咱们转到有关事件的介绍。
若是您在Channel9观看了C#基础系列(C# Fundamentals series),在最后的视频中咱们讨论了事件。在Windows Phone API中,页面和控件在其生命周期的关键时刻或与终端用户交互过程当中引起事件。在本系列中咱们已经将PlayAudioButton的Click事件“链接”到一个称为“事件处理程序”的方法。当使用术语“事件处理程序”时,它指的是与事件关联的方法。我使用术语“链接”的意思是事件被绑定到特定的事件处理程序方法。一些事件能够被用户触发,好比按钮控件的Click事件,其余事件在事件的生存期内发生,例如Loaded事件在给定的页面或控件对象被手机API运行时引擎实例化后发生。
有两种将页面或控件“链接”到事件处理程序的方法。第一种是使用XAML的属性语法。咱们已经在PlayAudioButton示例中作过了:
若是您回想一下,咱们输入:
Click="
而且在咱们输入结束双引号以前,智能感知询问咱们是否须要选择或建立一个事件处理程序。咱们告诉它须要以建立一个新的事件处理程序,Visual Studio将使用以下命名约定命名事件处理程序:
NameOfElement_EventName
因此在咱们的例子中,事件处理程序的名称是:
PlayAudioButton_Click
Visual Studio同时在XAML页面的代码隐藏文件中建立了一个方法存根,在本例中代码隐藏文件是MainPage.xaml.cs。请记住这就是Visual Studio自动化。当智能感知第一次出现时,咱们能够敲键盘上的escape键并手工输入代码。
关联事件与事件处理程序的第二中方法是使用Visual Studio中的属性窗口。
(1)首先您必须确认已经经过将鼠标放置在某个元素上以选择要编辑的控件。元素的名称将出如今顶部的名称字段,这使您知道设置的对象。也就是说您所作的任何设置将针对PlayAudioButton,而不是页面上的另外一个控件。
(2)单击闪电图标。这将切换到一个属性列表,在属性窗口中能够更改该控件能够处理的事件。
(3)双击某个特定的文本框以建立控件的事件和事件处理程序之间的关联。双击将自动命名事件并为您在代码隐藏文件中建立一个方法存根。
第三种技术(咱们将在本系列中使用数次)是在C#代码中链接事件处理程序。见下面示例中的第35行:
+=运算符在其余上下文中表示“增长并设置”,所以:
x += 1;
等同于
x = x + 1;
在某种意义上,这里也是如此。咱们须要“添加并设置”Click事件到另外一个事件处理程序方法。是的,myButton的Click事件能够被设置为触发多个事件处理程序的执行。这里咱们说:“当Click事件被触发时,将PlayAudioButton_Click事件处理程序添加到应该被执行的事件处理程序的列表。”一个Click事件能够触发一个或更多方法的执行。在咱们的应用程序中只有一个事件处理程序 PlayAudioButton_Click将被执行。
您可能想知道为何那行代码不是这样:
myButton.Click += PlayAudioButton_Click();
请注意_Click后面的括号。回忆一下C# Fundamentals系列,()表明方法调用运算符。换句话说,当咱们使用()时,咱们告诉运行时当即执行那行代码中的方法。那不是咱们想要的,咱们仅仅须要关联或指向PlayAudioButton_Click方法。
有关事件处理程序的另外一个有趣的注意事项:当我在35行添加了以上代码后,如今咱们有两个事件同时指向同一个事件处理程序方法PlayAudioButton_Click。这是彻底合法的。那么咱们如何肯定是哪一个按钮触发了方法的执行?
若是您看一下PlayAudioButton_Click方法的定义:
private void PlayAudioButton_Click(object sender, RoutedEventArgs e)
{
}
Windows Phone运行时将sender(发送者)做为输入参数传递。由于咱们能够将该事件关联到任意控件,而且sender的类型是Object(.Net框架中几乎全部的数据类型最终都从Object类型派生),因此咱们须要作的第一件事情是进行一些检查以肯定实际的数据类型(你是一个按钮控件吗?你是一个正方形控件吗?),而后将Object强制转换为特定的数据类型。例如,一旦咱们将Object强制转换为Button,那么咱们就能够访问Button的属性了。
上述代码片断中方法的签名是Windows Phone API中的典型用法。除了输入参数sender,还有RoutedEventArgs参数, 它用于传递事件的额外信息。您将会看到如何在高级场景中使用它们,可是本系列中不会对其进行讨论。
综上所述,本课的重点是如何控制页面和控件的布局。对于Grid布局,咱们学习了使用自动缩放、比例缩放和像素缩放来定义行和列的高度和宽度的不一样方法。咱们讨论了垂直对齐和水平对齐如何将控件拉到边界,而边距如何将控件推离边界。而后咱们讨论了将事件链接到事件处理程序的不一样方法以及事件处理程序方法的输入参数。