Silverlight提供了一个灵活的系统用于在页面上布置界面元素、支持绝对定位和相对定位的布局。布局用于描述在屏幕上元素的过程,为了使界面更具有吸引力、更实用、更灵活,必须花大量的时间来设计界面,Silverlight使用容器来安排布局。每个容器有它自己的布局逻辑,Silverlight注重于创建更加灵活的布局,开发人员能够创建与显示分辨率和窗口无关的、在不同的显示器上可以很好地进行缩放的用户界面,当窗口内容发生变化时可以调整它们自己。
布局由所使用的容器决定,在容器中添加其它元素,一个典型的布局应当遵循以下的原则:
     容器可以被嵌套。Grid面板是功能最强大的布局控件,可以包含其他布局容器,这些容器以分组来安排元素,如文本框、列表框、工具条、按扭等
     不使用屏幕坐标指定元素的位置。各元素应当由它们的容器,根据它们的尺寸、顺序以及其他特定于具体布局容器的信息进行安排。
     不应显式设定元素的尺寸。元素应当可以自动改变以适合它们的内容。
     容器与元素动态使用多余的空间。如果空间允许,布局容器尽可能为它所包含的元素设置更合适的尺寸。
   所有容器类都是从Panel抽象类中派生出来的,Panel类提供了少量的共同成员,如下二个常用公有属性:
     Background属性为面板背景着色的画刷。
     Children属性是在面板存储的元素集合。
几种布局面板中,最常用的是布局控件是Canvas、StackPanel、Grid,Grid使用的是精确坐标,StackPanel则是使用相对坐标完成布局定义的,在该面板包含的元素使用Margin等属性,最复杂的是Grid,当Grid只有一行和一列的时候,它在功能上等同于一个Canvas,只是Canvas只可以使用绝对坐标而Grid可以使用Margin等相对属性,另外Grid还可以仿StackPanel布局方式,只是使用Grid模访的过程不如直接使用StackPanel更方便。
 

范例 示范使用综合布局

实际中,往往将各类布局综合使用,他们可以相互包容,以达到预期设计效果,图3.4-1 Ch6_Exam4_1运行的结果。
                             3.4-1
◎如下所示,MainPage.xaml的主要XAML标记摘录如下,其中已添加完整的批注
<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="Ch6_Exam4_1.MainPage"
    Width="800" Height="450" Background="Red">
<Border Background="#FF958B8B">
    <Grid x:Name="LayoutRoot" Background="White" Margin="40,5,40,5">
 
<!—定义三行三列,中间一行和一列作为边框 à
           <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="Auto"/>
                  <ColumnDefinition Width="8"/>
                  <ColumnDefinition/>
           </Grid.ColumnDefinitions>
           <Grid.RowDefinitions>
                  <RowDefinition Height="Auto" />
                  <RowDefinition Height="8"/>
                  <RowDefinition/>
           </Grid.RowDefinitions>
 
<!—标题放Border元素内,定义背景渐变效果 à
           <Border Grid.ColumnSpan="3" > 
             <Border.Background>
    <LinearGradientBrush EndPoint="0.502,2.158" StartPoint="0.472,-1.366">
                     <GradientStop Color="#FFECDDDD" Offset="0.404"/>
                     <GradientStop Color="#FF0E4EBD" Offset="1"/>                     
                    </LinearGradientBrush>
             </Border.Background>     
           <TextBlock   Text="2010汽车排行榜"  TextWrapping="Wrap" FontSize="26.667" FontWeight="Bold" HorizontalAlignment="Center" Width="252" Foreground="#FFD42525"/>
           </Border>
    <Border Background="#FF958B8B" Grid.Row="1" Grid.ColumnSpan="3" />
           <Border Background="#FF958B8B" Grid.Column="1" Grid.Row="1" />
           <Border Background="#FF958B8B" Grid.Column="1" Grid.Row="2" />   
           <Border Background="#FF958B8B" Grid.Row="2" > 
 
<!--使用样式资源 -->
           <ListBox x:Name="lstBox"   Style="{StaticResource txtList}" SelectionChanged="SelectionChanged_Click" ScrollViewer.VerticalScrollBarVisibility="Visible">
                  <ListBoxItem  Content="高尔夫6"/>
                         <ListBoxItem Content="新明锐"/>
                         <ListBoxItem Content="速腾1.4T" />
                         <ListBoxItem Content="福克斯两厢" />
                         <ListBoxItem Content="科鲁兹" />                   
           </ListBox>
           </Border>
 
<!--呈现动态XAML页面 -->
           <Border  Grid.Column="2" Grid.Row="2" Background="#FF958B8B" >
           <StackPanel x:Name="MyPanel">
           </StackPanel>
           </Border>             
    </Grid>
    </Border>
</UserControl>
◎     为各车型ListBoxItem SelectionChanged事件处理编写如下程序代码,在Panel中动态加载XAML界面的实例。
void SelectionChanged_Click(object sender, SelectionChangedEventArgs e)
        {
                  ListBoxItem Car=((ListBox)sender).SelectedItem as ListBoxItem;
                  switch  (Car.Content.ToString())
                  {
                         case "高尔夫6":
                                this.MyPanel .Children .Clear ();
<!—加载高尔夫6界面,创建Golf.xaml的实例并将它添加到MyPanel à
                                this.MyPanel.Children.Add(new Golf ());
                                break;
                         case "新明锐":
                                this.MyPanel .Children .Clear ();
<!--加载新明锐界面,创建Mingrui.xaml的实例并将它添加到MyPanel -->
                                this.MyPanel.Children.Add(new Mingrui ());
                                break;    
                         case "速腾1.4T":
                                this.MyPanel .Children .Clear ();
<!--加载速腾1.4T界面,创建Shuteng.xaml的实例并将它添加到MyPanel -->
                                this.MyPanel.Children.Add(new Shuteng ());
                                break;
                         case "福克斯两厢":
                                this.MyPanel .Children .Clear ();
<!--加载福克斯两厢界面,创建Fukesi.xaml的实例并将它添加到MyPanel --
                             this.MyPanel.Children.Add(new Fukesi ());
                                break;           
                         case "科鲁兹":
                                this.MyPanel .Children .Clear ();
 
<!--加载科鲁兹界面,创建Kouluz.xaml的实例并将它添加到MyPanel -->
                          this.MyPanel.Children.Add(new Kouluz ());
                                break;
                  }
◎在App.xaml定义全局新式资源
    <Application.Resources>
<!--各车型介绍文字 -->
          <Style x:Key="txtBlock" TargetType="TextBlock">
                 <Setter Property="FontSize" Value="15" ></Setter>
                    <Setter Property="FontWeight" Value="Bold"></Setter>
                    <Setter Property="Foreground"  Value="Red"></Setter>
                    <Setter Property="TextWrapping" Value="Wrap"></Setter>
                    <Setter Property="FontFamily" Value="Arial"></Setter>
             </Style>     
 
<!--各车型名称 -->
             <Style x:Key="txtList" TargetType="ListBox">
                 <Setter Property="FontSize" Value="18" ></Setter>
                    <Setter Property="Foreground"  Value="Blue"></Setter>
                    <Setter Property="FontFamily" Value="Arial"></Setter>
             </Style>     
    </Application.Resources>
◎定义各车型介绍的xaml界面,下面为福克斯的Fukesi.xaml文件,其它车型文件类同。
    <Grid x:Name="LayoutRoot">
           <Image  Source="Img/fukes.jpg" Stretch="UniformToFill"/>
<!--介绍文字的TextBlock,使用样式资源 -->
           <TextBlock Height="Auto" Margin="66,0,126,0" Text=" 09款福克斯比较07款在节油技术上作了大幅度的提升,包括最新调校的可变正时气门技术、更低的风阻系数以及选择轻量化的新一代轮毂。"  Style="{StaticResource txtBlock}" />
    </Grid>
</UserControl>

3.2 导航模板

Silverlight 应用程序中使用 Frame Page 控件可以实现应用程序导航。页面控件表示内容的分立部分。框架用作页面控件的容器,并使页导航非常简便。在任一时刻,框架只显示一个页面的内容。以编程方式或通过用户操作导航到新页时,框架中显示的页将会更改。
可以将 Silverlight 应用程序的根视觉效果设计为包含可导航内容和永久用户界面 (UI) 组件(例如页眉、页脚和导航边栏)的组合。使用"Silverlight 导航应用程序"模板创建新项目时,该模板会生成一个包含永久 UI 组件的 XAML 文件并为可导航内容生成一个框架。
Visual Studio 中的Silverlight导航应用程序模板:“Silverlight Navigation Appication”,默认的模版向我们提供了一个MainPage.xaml页面并给出了一个大致的主页视图。导航框架XAML代码如下:
<Grid x:Name="LayoutRoot" Style="{StaticResource LayoutRootGridStyle}">
<Border x:Name="ContentBorder" Style="{StaticResource ContentBorderStyle}">
<navigation:Frame x:Name="ContentFrame" Style="{StaticResource ContentFrameStyle}"
   Source="/Home" Navigated="ContentFrame_Navigated" NavigationFailed="ContentFrame_NavigationFailed">
                <navigation:Frame.UriMapper>
                  <uriMapper:UriMapper>
        <uriMapper:UriMapping Uri="" MappedUri="/Views/Home.xaml"/>
                    <uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>
                  </uriMapper:UriMapper>
                </navigation:Frame.UriMapper>
            </navigation:Frame>
        </Border>
<Grid x:Name="NavigationGrid" Style="{StaticResource NavigationGridStyle}">
<Border x:Name="BrandingBorder" Style="{StaticResource BrandingBorderStyle}">
<StackPanel x:Name="BrandingStackPanel" Style="{StaticResource BrandingStackPanelStyle}">
                    <ContentControl Style="{StaticResource LogoIcon}"/>
                    <TextBlock x:Name="ApplicationNameTextBlock" Style="{StaticResource ApplicationNameStyle}"
                               Text="Application Name"/>
                </StackPanel>
            </Border>
 <Border x:Name="LinksBorder" Style="{StaticResource LinksBorderStyle}">
<StackPanel x:Name="LinksStackPanel" Style="{StaticResource LinksStackPanelStyle}">
 
      <HyperlinkButton x:Name="Link1" Style="{StaticResource LinkStyle}"
                                     NavigateUri="/Home" TargetName="ContentFrame" Content="home"/>
     <Rectangle x:Name="Divider1" Style="{StaticResource DividerStyle}"/>
<HyperlinkButton x:Name="Link2" Style="{StaticResource LinkStyle}"
   NavigateUri="/About" TargetName="ContentFrame" Content="about"/>
                </StackPanel>
            </Border>
        </Grid>
    </Grid>
</UserControl>
◎     Frame是一片可以被导航的区域。可以指定一个默认的视图,任何导航都可以在那片区域被触发,Frame 类提供用于页导航的方法和属性。将 Source 属性设置为要显示的页的 URI,或调用 Navigate 方法并将该页的 URI 作为参数来传递。
◎     UriMapper元素了定义了导航终端,可以用/Home终端来映射/View/Home.xaml终端。
◎     HyperlinkButton一超链按钮,其TargetName定义了目标框架区域。HyperlinkButton 控件位于框架外时,可以通过将 NavigateUri 属性设置为映射到某一页的 URI 并将 TargetName 属性设置为该框架的名称来启用对该框架内资源的导航。
◎     各个Page页面,在Views目录下,如默认的Home.xaml、About.xaml等。