Silverlight入门:第二部分 定义界面布局和导航

理解XAML应用程序中的布局管理是开发成功Silverlight应用的一个重要方面 。对于大多数来自Web领域的人来说,如果你对CSS不熟悉,那么这将成为你面临 的最大的挑战之一。

理解布局选项

Silverlight提供了一个灵活 的系统用于在页面上布置界面元素。布局模型同时支持绝对定位和相对定位的布 局风格。虽然提供了多种布局控件,但最常用的是:

Canvas

StackPanel

Grid

让我们逐个看看当把元素放在其中的时 候,它们是如何工作的。我们将使用一个简单的按钮元素来演示。我们使用本系 列第一部分创建的项目,并在Home.xaml页面作简单的演示。

Canvas

Canvas是最基础的布局控件,被用于通过坐标绝对地定位 元素。你可以通过在Canvas中附加属性来定位元素。附加属性允许父容器(在这 个例子中是Canvas)扩展在它之中的控件的属性(在这个例子中是按钮)。我们 可以在Canvas中像这样放置很多按钮:

1: <Canvas>
  2:   <Button Canvas.Top="50" Canvas.Left="50"  Content="Button 1" FontSize="18" Width="150" Height="45" />
  3:   <Button Canvas.Top="150" Canvas.Left="20"  Content="Button 2" FontSize="18" Width="150" Height="45" />
  4:   <Button Canvas.Top="70" Canvas.Left="80"  Canvas.ZIndex="99" Content="Button 3" FontSize="18" Width="150"  Height="45" />
  5: </Canvas>

显示效果 如下:

可以看到,这是绝对定位布局的方法。注意到在这个例子中,我也可以通过 指定扩展属性ZIndex使得一个按钮叠加在另一个上面。这可能有助于像是游戏开 发或者高物理环境这样对计算非常精确的场合。Canvas在位置移动不太大,或是 你想漂亮地控制应用程序的尺寸时是很有用的。然而,Canvas有时不像 StackPanel和Grid那么容易利用。

StackPanel

StackPanel是垂直或水平堆叠元素的布局控件(默认是垂直的)。示例代码 如下:

1: <StackPanel>
2:   <Button Margin="10"  Content="Button 1" FontSize="18" Width="150"  Height="45" />
3:   <Button Margin="10" Content="Button  2" FontSize="18" Width="150" Height="45" />
4:    <Button Margin="10" Content="Button 3" FontSize="18"  Width="150" Height="45" />
5: </StackPanel>

显示效果如下:

或者如果我们通过代码将默认的方向属性改成水平的(注意方向属性是唯一 的区别):

1: <StackPanel Orientation="Horizontal">
2:    <Button Margin="10" Content="Button 1" FontSize="18"  Width="150" Height="45" />
3:   <Button Margin="10"  Content="Button 2" FontSize="18" Width="150"  Height="45" />
4:   <Button Margin="10" Content="Button  3" FontSize="18" Width="150" Height="45" />
5:  </StackPanel>

显示效果如下:

StackPanel提供了一种使元素互相顶着或靠着的简单方式,让你不必花很大 精力在定位容器中的控件元素。

Grid

Grid是大多数情况下最灵活的布局(注意我说的是大多数,不是所有)。和 听起来一样,Grid通过行与列来安排位置。不像网站开发可能要在 <table>元素中放置<tr>、<td>标签那样,XAML Grid用法是 不同的。你定义Grid的整体结构以后,通过附加属性告诉元素把它们放在哪里。

考虑如下代码(注意我明确地显示了Grid的网格,但你不必每次都那么做, 我只是为了使显示更加形象化)。

1: <Grid ShowGridLines="True">
2:    <Grid.RowDefinitions>
3:     <RowDefinition  Height="60" />
4:     <RowDefinition  Height="60" />
5:     <RowDefinition  Height="60" />
6:   </Grid.RowDefinitions>
7:
8:    <Grid.ColumnDefinitions>
9:      <ColumnDefinition Width="175" />
10:      <ColumnDefinition Width="175" />
11:      <ColumnDefinition Width="175" />
12:    </Grid.ColumnDefinitions>
13:
14:   <Button  Grid.Column="0" Grid.Row="0" Content="Button 1" FontSize="18"  Width="150" Height="45" />
15:   <Button  Grid.Column="2" Grid.Row="0" Margin="10" Content="Button 2"  FontSize="18" Width="150" Height="45" />
16:   <Button  Grid.Column="1" Grid.Row="2" Margin="10" Content="Button 3"  FontSize="18" Width="150" Height="45" />
17:  </Grid>

我们定义了一个3行3列的Grid并定义了宽和高。注意在按钮元素中我们使用 了附加属性来定位它们在Grid中的位置。

显示效果如下:

注意按钮上的附加属性(Grid.Column、Grid.Row)是如何告诉元素把自己定 位在容器的哪个位置的。在Expression Blend中做布局的工作是非常有帮助的。 注意在Blend中你可以通过向导可视地指定行和列的定义,同时它将为你生成 XAML:

箭头所指的向导告诉你行和列是否是固定尺寸的(锁定)。我们将在我们的 应用程序中使用多种布局控件。事实上,我们选择的默认模版已经为我们的应用 程序的基本框架提供了所有不同类型的布局控件。构建我们的Twitter应用程序

现在我们可以构建我们的应用程序了。总的来说,这是我们要做的程序的样 例。

注意到我们将为用户提供一个地方去输入搜索条件,并将结果通过列表显示 出来。我们也有导航区可以显示不同的内容,像是历史查询或是一些可能的统计 。

幸运的是我们选择的导航模版已经送了我们的整体布局一个大礼。我们只需 要在MainPage.xaml做一点点改动。在MainPage.xaml 的第29行,我们移除应用 程序的Logo,然后把它下面的内容改成Twitter Search Monitor。我们将很快回 来,不过现在先让我们切换到我们的视图。在视图文件夹的项目结构中右击并在 Visual Studio中选择创建新页,并选择创建一个新Silverlight页,将其命名为 Search.xaml:

现在你应该已经获得了一个包含默认Grid布局的空白XAML页面。我们 将在这里创建在上面看到的搜索屏幕。我们从MainPage.xaml获取头信息是因为 我们将使用框架元素来承载我们的应用程序。Silverlight导航框架

在这一节,让我们切入并了解Silverlight导航框架。如果你还记得我们 开始时使用的导航应用程序模版。默认的模版向我们提供了一个 MainPage.xaml 页面并给出了一个大致的主页视图。导航框架基本上由3部分组成:UriMapper、 Frame以及Page。

UriMapper

我喜欢把UriMapper元素当作是各种 各样的路由引擎。它并不总是必须的,但我认为它能模糊并简化你的导航终端。 你可以用/Home终端来映射 /View/Home.xaml终端,使得它更容易阅读并且不会 丢失任何技术配置。你以后还可以修改它,让它映射到其它地方。你可以看见 UriMapper作为MainPage.xaml页面中框架的一个元素:

1:  <navigation:Frame x:Name="ContentFrame" Style="{StaticResource  ContentFrameStyle}" Source="/Home"  Navigated="ContentFrame_Navigated"  NavigationFailed="ContentFrame_NavigationFailed">
  2:    <navigation:Frame.UriMapper>
  3:      <uriMapper:UriMapper>
  4:        <uriMapper:UriMapping Uri="" MappedUri="/Views/Home.xaml"/>
  5:       <uriMapper:UriMapping Uri="/{pageName}"  MappedUri="/Views/{pageName}.xaml"/>
  6:      </uriMapper:UriMapper>
  7:    </navigation:Frame.UriMapper>
  8:  </navigation:Frame>

现在像上面显示的那样,UriMapper在XAML里面。但它也可以包含资源,如果 要那样做的话,你可以像这样将它添加到框架元素中(假设资源是 UriMapperRoutes):

(此处原文未给出代码)

Frame

如果你是一名ASP.NET开发者,那么你可以把Frame元素当作是 ContentPlaceholder控件。Frame是一片可以被导航的区域。你可以指定一个默 认的视图,但是之后我们可以看到任何导航都可以在那片区域被触发。看上面的 代码,你可以看到一个默认的视图,Frame的 Source属性是为应用程序提供路由 的"/Home"。

Page

最后要说的基本导航区是只在最后一步创建的Page元素。它们是在Frame元素 中显示的非常基本的内容区域。它们与你通常添加的UserControl很相似,但是 特别之处在于它们可以导航。我们将考虑把我们的应用程序作为页面元素。

你可以通过以下视频了解更多关于导航的知识:

Silverlight的导航框架

简单地挖掘一遍它的功能就能受益无穷。框架允许深度连接到Silverlight应 用程序。

为我们的搜索视图创建界面布局

让我们为刚刚创建的Search.xaml页面创建一个界面。在这一节你可能对XAML 中所有的{StaticResource XXXXXXXX}元素感到困惑,我们将在第五部分的造型/ 模版章节作详细介绍,所以现在先跳过它们。注意我们的程序样例,我们需要一 个输入框、一个按钮和一个数据显示表格。让我们通过Blend来放置它们。要做 到这点,需要在Visual Studio中右击Search.xaml并选择在Blend中编辑:

因为Blend与Visual Studio共享同一个项目结构,所以你可以在编码以前同 时打开相同的文件来做XAML的可视化编辑。

在Blend中我们将放置一个两行的表格,一行用于放置搜索输入框和按钮,另 一行放置结果视图。在首行我们拖入一个StackPanel控件,并在其中放入一个 TextBox和一个Button,并将它的方向改为水平。

下一步我们将放置一个DataGrid用于显示数据。因为DataGrid不是核心控件 ,它在SDK库里,所以我们需要添加对它的引用。你可以在许多地方这样做,但 Blend其实会自动为你完成这样的工作。在Blend的工具箱中点击两次箭头并查找 DataGrid:

找到以后,选中它并把它拖到第二行。Blend会自动为你添加 System.Windows.Controls.Data.dll的引用并改变XAML文件中的标记。

1: <navigation:Page
2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 :      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4:      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5:      xmlns:mc="http://schemas.openxmlformats.org/markup- compatibility/2006"
6:     mc:Ignorable="d"
7:      xmlns:navigation="clr- namespace:System.Windows.Controls;assembly=System.Windows.Controls.Nav igation"
8:     xmlns:data="clr- namespace:System.Windows.Controls;assembly=System.Windows.Controls.Dat a" x:Class="TwitterSearchMonitor.Views.Search"
9:      d:DesignWidth="640" d:DesignHeight="480"
10:      Title="Twitter Search Page">
11:   <Grid  x:Name="LayoutRoot">
12:      <Grid.RowDefinitions>
13:       <RowDefinition  Height="32"/>
14:       <RowDefinition/>
15:      </Grid.RowDefinitions>
16:     <StackPanel  HorizontalAlignment="Left" Margin="0,-32,0,0"  VerticalAlignment="Top" Grid.Row="1"  Orientation="Horizontal">
17:       <TextBox  x:Name="SearchTerm" FontSize="14.667" Margin="0,0,10,0" Width="275"  TextWrapping="Wrap"/>
18:       <Button  x:Name="SearchButton" Width="75" Content="SEARCH"/>
19:      </StackPanel>
20:     <data:DataGrid  x:Name="SearchResults" Margin="0,8,0,0" Grid.Row="1"/>
21:    </Grid>
22: </navigation:Page>

注意顶部的xmlns:data,这就是你为在XAML中使用非核心控件而添加的程序 集的引用。接着使用它们你就能在Grid中看到data:Grid元素。你的XAML现在看 上去应该和我一样,就像这样:

注意在XAML中,我为TextBox、Button和DataGrid分别设置了x:Name,分别是 SearchTerm、SearchButton以及SearchResults,这将帮助我以后很容易地找到 它们。

现在如果你回到Visual Studio你将会看到一个询问是否重新读取项目的提示 框。这是因为Blend添加了对DataGrid控件的引用,从而改变了项目文件。你可 以选择重新读取继续下去。这显示了开发工具是如何在项目文件层面进行整合的 ,现在我们可以再次用VS来编写代码了。

改变Search.xaml的默认UriMapper

现在我们只是创建了搜索页(这基本上是我们应用程序的主页),接着让我 们来为导航框架做一些改变。在MainPage.xaml找到Frame,并将默认的/Home改 为我们的搜索页,并且其它几处地方也做同样的更改。你的Frame XAML看起来应 该像这样:

1: <navigation:Frame x:Name="ContentFrame"  Style="{StaticResource ContentFrameStyle}" Source="/Search"  Navigated="ContentFrame_Navigated"  NavigationFailed="ContentFrame_NavigationFailed">
2:    <navigation:Frame.UriMapper>
3:      <uriMapper:UriMapper>
4:        <uriMapper:UriMapping Uri=""  MappedUri="/Views/Search.xaml"/>
5:        <uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/ {pageName}.xaml"/>
6:      </uriMapper:UriMapper>
7:    </navigation:Frame.UriMapper>
8:  </navigation:Frame>

因为我们不需要Home.xaml,所以继续在项目中的其它地方删除它。同时添加 一个叫作History.xaml的新视图,同时改变MainPage.xaml的LinkBorder,使它 包含一个链接,像这样:

1: <Border x:Name="LinksBorder" Style="{StaticResource  LinksBorderStyle}">
2:   <StackPanel  x:Name="LinksStackPanel" Style="{StaticResource  LinksStackPanelStyle}">
3:     <HyperlinkButton  x:Name="Link1" Style="{StaticResource LinkStyle}"  NavigateUri="/Search" TargetName="ContentFrame"  Content="home"/>
4:     <Rectangle x:Name="Divider1"  Style="{StaticResource DividerStyle}"/>
5:      <HyperlinkButton x:Name="Link2" Style="{StaticResource  LinkStyle}" NavigateUri="/History" TargetName="ContentFrame"  Content="history"/>
6:     <Rectangle x:Name="Divider2"  Style="{StaticResource DividerStyle}"/>
7:      <HyperlinkButton x:Name="Link3" Style="{StaticResource  LinkStyle}" NavigateUri="/About" TargetName="ContentFrame"  Content="about"/>
8:   </StackPanel>
9:  </Border>

现在如果我们运行起来,效果应该像这样:

现在我们已经有了一个基础布局,让我们在第三部分添加数据。

Powered By D&J (URL:http://www.cnblogs.com/Areas/)
原文地址:https://www.cnblogs.com/Areas/p/2169788.html