第二章 开始认识XAML (3)

标记扩展

标记扩展是一种需要说明的用于指定属性值的特殊语法。此种说明取决于所用的标记扩展。标记扩展以大括号{开始,紧跟标记扩展名,后面的参数作为标记扩展的可选内容,最后以}结束。通过这些内容来支持Silverlight的一些关键特性,包括资源、数据绑定和模板绑定。我们将在这里简要讨论一下每种特性并以高亮语法来讲解标记扩展。


注意 在您初次接触标记扩展时可能会觉得很怪异(如类型转换)。标记扩展提供了一种指定更多简单类型值的机制-他们代替了以往很多复杂的处理过程,如通过样式完全改变用户界面外观。如果您希望显式地在大括号中显示一些内容,如一个label标签,您必须将一个空内容的一组大括号放置于最前面-例如{}{文本内容}

资源字典与引用静态资源

为了让用户不感到陌生应用程序应始终保持界面一致性,包括使用相同的颜色、字体和字号,样式和模板(用于控制控件中的项如何呈现或改变默认控件的外观)。定制化常用于创建这种一致外观的应用程序。当您改变任何细节时,如颜色,您只需要在一处修改就会将这种改变反映在整个应用程序的控件或者XAML页中,这一点类似CSS样式表。

用于保存这些定制化内容的地方叫做资源字典(resourcedictionary)。资源字典已键值对的形式进行关联。这一点非常像您以前使用过的字典集合Dictionary<string, object>。在XAML中,键通过x:key属性进行设置。任何对象都包含Resources成员来包含资源。包含了布局容器(此内容您将会在下一章节碰到),App.xaml文件提供了整个应用程序的资源(可以理解为全局资源)。

让我们再来看一下前面提到的登录界面,此登录界面使用了资源字典来指定字体样式。将字体配置为不同的值后,界面将会发生轻微的变化。您可以通过图示2-5来查看运行效果。资源字典使改变标题和文本标签的外观变得更加容易。

image

图2-5.由样式资源指定的字体属性

再来看看以下登录界面的XAML代码,新加入的代码以粗体显示:

<Canvas Width="300" Height="Auto" x:Name="canvasTag">
            <Canvas.Resources>
                <Style x:Key="LoginHeaderFontStyle" TargetType="TextBlock">
                    <Setter Property="FontFamily" Value="Times New Roman"/>
                    <Setter Property="FontSize" Value="20"/>
                </Style>
                <Style x:Key="LoginLabelFontStyle" TargetType="TextBlock">
                    <Setter Property="FontFamily" Value="Arial"/>
                    <Setter Property="FontSize" Value="14"/>
                </Style>
            </Canvas.Resources>
                <Grid Height="140" Width="250" Canvas.Left="25" Canvas.Top="15">
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition/>

</Grid.ColumnDefinitions>
                    <TextBlock HorizontalAlignment="Center"
                    Text="Please enter your information"
                    Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2"
                         Style="{StaticResource LoginHeaderFontStyle}" />
                    <TextBlock Text="Username:" VerticalAlignment="Top"
                    HorizontalAlignment="Right"
                    Grid.Column="0" Grid.Row="1"
                         Style="{StaticResource LoginLabelFontStyle}"/>
                    <TextBox VerticalAlignment="Top" Grid.Column="1" Grid.Row="1"/>
                    <TextBlock HorizontalAlignment="Right" VerticalAlignment="Top"
                    Grid.Column="0" Grid.Row="2" Text="Password:"
                           Style="{StaticResource LoginLabelFontStyle}">
                    </TextBlock>
                    <TextBox VerticalAlignment="Top" Grid.Column="1" Grid.Row="2"/>
                    <Button Content="Login" Grid.Row="3"
                           Width="100" Grid.Column="1" HorizontalAlignment="Left"/>
                </Grid>
            </Canvas>

要引用静态资源,您需要一种方法来告诉XAML分析器,您想要使用资源并且要使用那个资源。引用静态资源的标记扩展名写作StaticResource,并且紧跟在左大括号后。StaticResource标记扩展需要提供一个参数:所引用的资源名称。

在标记扩展中x:key属性用于给每个样式一个名称来进行引用。我们将在第八章讨论样式的详细内容,样式元素的TargetType属性用于指定目标对象的类型,Setter元素用于指定该目标类型的属性值。既然如此,我们定义两种样式:一种用于标题文本(内容为Please enter your information),另外一个是文本框旁边的文本标签。通过改变LoginLabelFontStyle,您可以同时影响用户名和密码文本标签。这真是好极了-为应用程序套用样式变得更加容易,这得益于样式的集中化管理并且进需要一个单独的样式文件来影响界面上的许多元素。


注意 虽然您可以从资源字典里面使用{StaticResource}来引用字典中的其他资源,但是您仅能引用那些在引用前显示的资源。

Silverlight 3通过整合的资源字典为资源字典提供了更多的能力。因此,您可以引用资源字典存储在xap文件的内容文件中,甚至是另外一个程序集的xap文件中。外部资源字典通过ResourceDictionary类的Source属性来引用。前面的例子用了两种样式,一种用于标题,另外一种用于文本标签。让我们将这两个样式分别放置在独立的XAML文件中。用于标题样式的资源字典被定义在ExternalResources1.xaml文件中。

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <Style x:Key="LoginHeaderStyle_External" TargetType="TextBlock">
        <Setter Property="FontFamily" Value="Times New Roman"/>
        <Setter Property="FontSize" Value="20"/>
    </Style>
</ResourceDictionary>

用于文本标签样式的资源字典被定义在ExternalResources2.xaml文件中。这些文件就像普通的xml文件一样添加到Visual Studio工程中(只是扩展名是xaml而已),并且他们的编译动作(Build Action)由Page更改为Content。此设置是为了确保这些文件被整合到XAP文件中。从此Canvas中不再包含这些样式定义,由MergedDictionaries属性来指定导入哪个外部资源字典。

<Canvas.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/ExternalResources1.xaml"/>
            <ResourceDictionary Source="/ExternalResources2.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Canvas.Resources>

Source属性的值指定为一个URI对象来定位使用哪个外部资源字典。Source属性值能指定一个资源字典文件。

我们将在第八章详细介绍整合资源字典特性。

数据绑定(Data Binding)

数据绑定用来将用户界面和数据源进行关联的一种方式。数据绑定可以将数据从数据源传输到用户界面来反映一次或多次的数据改变,它可以保证数据源和用户界面始终保持同步。用于控制绑定的标记扩展称作Binding,有四种可用的选项。让我们想象一下用户访问在线银行的登录授权界面吧。用户登录后,他们可以选择账户中的一个进行管理(也可以直接查看各个账户的余额信息),如图2-6所示。

image

 

图2-6:账户对象绑定到ListBox控件中显示的结果

下面显示了一个相当简单的账户信息业务对象:

Code

现在我们在Visual Studio里面创建一个新的UserControl,并命名为ChooseAccount。您可以在工程上点击右键,然后点击添加->新建项->Silverlight UserControl。重命名为ChooseAccount.xaml最后点击确定按钮。编辑ChooseAccount.xaml.cs文件,创建一个泛型List来放置Account类型,这里我们想泛型List里面添加了两个Account对象。这将为数据绑定做好准备。

private List<Account> accountList;
public ChooseAccount()
{
   // Required to initialize variables
   InitializeComponent();
   accountList = new List<Account>();
   accountList.Add(new Account("Checking", 500.00));
   accountList.Add(new Account("Savings", 23100.19));
   accountListBox.DataContext = accountList;
}

请注意构造方法的最后一行代码---这就是数据源连接到ListBox的代码。这里ListBox的别名为accountListBox,这个名字是我们在xaml中定义的。用于绑定的标记扩展我们用粗体表示。(这里您还需要注意,我们已经将Grid布局控件替换成了StackPanel布局控件)

<UserControl
   xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   x:Class="XAMLTour.ChooseAccount">
   <StackPanel Orientation="Horizontal" Margin="30,30,0,0">
      <TextBlock Text="Choose account to manage: "></TextBlock>
      <ListBox x:Name="accountListBox" Height="100" Width="300"
                     VerticalAlignment="Top" ItemsSource="{Binding Mode=OneWay}">
         <ListBox.ItemTemplate>
            <DataTemplate>
               <StackPanel Orientation="Horizontal">
                  <TextBlock Text="{Binding AccountName}" />
                  <TextBlock Text=" ($"></TextBlock>
                  <TextBlock Text="{Binding AccountBalance}" />
                  <TextBlock Text=")"></TextBlock>
               </StackPanel>
            </DataTemplate>
         </ListBox.ItemTemplate>
      </ListBox>
   </StackPanel>
</UserControl>

标记扩展Binding

posted @ 2010-04-07 20:49  王一平  阅读(696)  评论(0编辑  收藏  举报