[译稿]Silverlight入门:第四部分——数据绑定

这是 Silverlight入门系列的第四部分。点击 这里可以查看本系列的目录。 你可以下载C#Visual Basic版本的本示例应用程序的完整项目文件。

在之前的第三部分中,我们做了很多工作来获取公共Web服务返回的数据并让其显示在控件中。我们已经用过了DataGrid控件,但它并不是我们真正想要的用户界面,所以让我们自己来定义一个。为此,我们需要一个ItemsControl和一个DataTemplate。这将让我们学习到XAML的绑定语法,以及如何利用更强大的数据绑定信息。

在开始之前——先删除DataGrid

在开始之前,让我们先删除并且只删除DataGrid,我们也不再需要它的程序集引用以及xmlns,所以也可以大胆删除它们。

把DataGrid替换成ItemsControl,像是这样:

1 < ItemsControl x:Name = " SearchResults " Margin = " 0,8,0,0 " Grid.Row = " 1 " />

这里我们又要用到Blend了,我们准备在Blend中为ItemControl修改ItemTemplate。ItemControl本质上只是一个按照我们要求工作的解析控件。如果我们仅仅只是把DataGrid替换成ItemControl,那么我们将得到:

gs4-itemscontrol

ItemControl不知道我们想如何显示数据,所以我们要在模板中告诉它……让我们回到Blend。通常我们都在这里编辑(前面说到过)。

gs4-templatemock

在框中显示发布消息的用户的头像。使用我们之前学到的布局知识可以很容易地创建模板。我们在Blend中放置一个ResultObjects并右击选择编辑ItemTemplate(在已生成项目菜单下)。

gs4-edittemplateblend

现在我们已经获得了一个可以填充内容的空模板。在随后的对话框中,我把它命名为SearchResultsTemplate。现在我们处于布局编辑模式,可以在其中拖拉或移动内容。我创建了一个基于表格的布局,这是我的模板的XAML:

1   < DataTemplate x:Key ="SearchResultsTemplate" >
2       < Grid Margin ="4,0,4,8" d:DesignWidth ="446" d:DesignHeight ="68" >
3           < Grid .ColumnDefinitions >
4               < ColumnDefinition Width ="Auto" />
5               < ColumnDefinition Width ="*" />
6           </ Grid.ColumnDefinitions >
7           < Border VerticalAlignment ="Top" Margin ="8" Padding ="2" Background ="White" >
8               < Image Width ="40" Height ="40" />
9           </ Border >
10
11         < StackPanel Grid.Column ="1" VerticalAlignment ="Top" Margin ="0,4,0,0" >
12             < TextBlock x:Name ="AuthorName" FontWeight ="Bold" />
13             < Grid Margin ="0,6,0,0" >
14                 < Grid .RowDefinitions >
15                     < RowDefinition Height ="Auto" />
1 6                     < RowDefinition Height ="2" />
17                     < RowDefinition Height ="Auto" />
18                 </ Grid.RowDefinitions >
19                 < TextBlock x:Name ="TweetMessage" TextWrapping ="Wrap" />
20                 < TextBlock x:Name ="PublishDateLabel" Grid.Row ="2" />
21             </ Grid >
22         </ StackPanel >
23     </ Grid >
24 </ DataTemplate >

我们还把ItemControl放入了ScrollViewer中,因为它本身没有提供滚动条:

1 < ScrollViewer Grid.Row ="2" HorizontalScrollBarVisibility ="Disabled" VerticalScrollBarVisibility ="Auto" BorderThickness ="1" >
2     < ItemsControl x:Name ="SearchResults" Margin ="0,8,0,0" Grid.Row ="1" ItemTemplate ="{StaticResource SearchResultsTemplate}" />
3 </ ScrollViewer >

现在我们已经设置完控件了,但是我们还没有告诉它如何处理接收到的数据。

XAML绑定语法

这里是我们写绑定语法的地方。你看,ItemsControl正在获取数据(记住,我们没有改变代码,所以SearchResults.ItemsSource仍然被设置为我们的PagedCollectionView)。我们需要使用绑定来将实体元素映射到模板。基本的XAML绑定语法是:

{Binding Path=<some-data-path>, Mode=<binding mode>}

你还能得到更多高级的功能,但我们将从简单的开始。比如说,将模板中的图像元素绑定到TwitterSearchResult模型的头像,看起来像这样:

1 < Image Width ="40" Height ="40" Source ="{Binding Path=Avatar, Mode=OneWay}" />

同时绑定作者到作者名称元素,像这样:

1 < TextBlock x:Name ="AuthorName" FontWeight ="Bold" Text ="{Binding Path=Author, Mode=OneWay}" />

我们将它们的模式设置成OneWay,因为在不需要改变数据的情况下不需要使用TwoWay。在发布日期的处理上,我们需要提供一些明确的数据格式,这可以通过值转换器做到。

绑定一个值转换器

值转换器是实现IValueConverter接口的一些类,它们提供了正向和反向的转换方法。我们打算在发布日期上采用明确的日期对象格式,所以我们将在项目中一个被叫做转换器的文件夹中创建一个名为DateTimeConverter.cs的类。这个类看起来像这样:

1   using System;
2   using System.Threading;
3   using System.Windows.Data;
4
5   namespace TwitterSearchMonitor.Converters
6   {
7         /*
8         * Use this converter for formatting dates in XAML databinding
9         * Example:
10       * Text="{Binding Path=PublishDate, Converter={StaticResource DateTimeFormatter}, ConverterParameter=MMM yy}" />
11       *
12       * */
13     public class DateTimeConverter : IValueConverter
14     {
15         #region IValueConverter Members
16
17         public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
18         {
19             DateTime ? bindingDate = value as DateTime ? ;
20
21             if (culture == null )
22             {
23                 culture = Thread.CurrentThread.CurrentUICulture;
24             }
25
26              if (bindingDate != null )
27             {
28                 string dateTimeFormat = parameter as string ;
29                 return bindingDate.Value.ToString(dateTimeFormat, culture);
30             }
31
32             return string .Empty;
33         }
34
35         public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
36         {
37             throw new NotImplementedException();
38         }
39
40         #endregion
41     }
42 }

我们要回到XAML页面来使用它(Search.xaml),还要为此添加xmlns声明和资源。我们要使用的xmlns看起来像这样:

1 xmlns:converters="clr-namespace:TwitterSearchMonitor.Converters"

之后在XAML中的资源节中(其它模板被定义的地方),我们将为转换器添加一个节点:

1 < navigation:Page .Resources >
2     < converters:DateTimeConverter x:Key ="DateTimeFormatter" />
3 ...

之后我们就能在PublishDateLabel元素上使用我们的转换器了,像这样:

1 < TextBlock x:Name ="PublishDateLabel" Text ="{Binding Path=PublishDate,
2     Converter={StaticResource DateTimeFormatter},
3     ConverterParameter=dd-MMM-yyyy hh:mm tt}" Grid.Row ="2" />

这将告诉XAML应该运行IValueConverter来得到输出。我们已经得到了想要的精确的数据格式。所有这些用于绑定的额外语法,使我们得到了期望的解析结果:

gs4-datatemplaterendered

没错,我知道用twitpic作为搜索关键字获得了一些有趣的结果,但那是因为用它作为搜索条件获得的数据刷新速度比较快!

很好,不是很难,不是吗?绑定语法对建设你的应用程序来说是至关重要的。

存储一些设置和配置数据

存储最后一次登陆的TwitterID对我们的应用程序来说是很有用的功能,这样当程序下一次启动的时候,就能从上次离开的地方继续。  此外,它还能保存搜索条件历史,使我们可以在历史导航中查看。

为此,我们将使用Silverlight中的独立存储。它可以为存储简单数据开启一个低信用度的用户区域。这里有更多关于独立存储的内容:

  • 使用Silverlight中的独立存储
  • 改变和增加独立存储配额

    要做到这一点,我将在Model文件夹中添加一个Helper类。这个辅助类将协助我们在独立存储区域保存和读取数据。独立存储的基础是在其中创建一个文件,并在需要的时候读取或写入数据。在我们的应用中,我们将用独立存储来保存键值对数据(搜索条件/TwitterID)。以下是Helper.cs类的内容:

    1   using System.IO.IsolatedStorage;
    2
    3   namespace TwitterSearchMonitor.Model
    4   {
    5       public class Helper
    6       {
    7            internal static string GetLatestTweetId( string searchTerm)
    8           {
    9               if (IsolatedStorageSettings.ApplicationSettings.Contains(searchTerm))
    10             {
    11                 return IsolatedStorageSettings.ApplicationSettings[searchTerm].ToString();
    12             }
    13             else
    14             {
    15                 return " 0 " ;
    16             }
    17         }
    18
    19         internal static void SaveLatestTweetId( string searchTerm, string latestId)
    20         {
    21             if (IsolatedStorageSettings.ApplicationSettings.Contains(searchTerm))
    22             {
    23                 IsolatedStorageSettings.ApplicationSettings[searchTerm] = latestId;
    24             }
    25             else
    26             {
    27                 IsolatedStorageSettings.ApplicationSettings.Add(searchTerm, latestId);
    28             }
    29         }
    30     }
    31 }

    现在在Search.xaml.cs中,我们将在活动指针被设置后在SearchForTweetsEx中添加如下内容:

    1 _lastId = Helper.GetLatestTweetId(SearchTerm.Text); // get the latest ID from settings
    2
    3 Helper.SaveLatestTweetId(SearchTerm.Text, _lastId); // saving for history even if a result isn't found

    在OnReadCompleted中,当我们关闭XMLReader后,还要添加如下内容:

    1 Helper.SaveLatestTweetId(SearchTerm.Text, _lastId); // saving last tweet id

    如果查找到搜索结果,则将查询条件和TwitterID存入独立存储。

    总结

    在本章节我们为控件设置了模板,并使用XAML语法绑定了一些简单的数据,还为格式化视图中的信息添加了一个值转换器,最后还用独立存储机制保存了设置信息。

    现在我们的程序已经可以正常工作了,接下来让我们为它锦上添花。

    让我们进入第五部分,我们将为本章节获得的数据添加一些新的控件以提高用户体验。

  • 你可能感兴趣的:(silverlight)