演练:在 Silverlight 业务应用程序中显示数据

在本演练中,您将创建一个 Silverlight 业务应用程序,该应用程序在两个不同的 Silverlight 页上显示来自 AdventureWorks 示例数据库的数据。第一页显示来自 SalesOrderHeader 表的数据,并且通过数据库记录提供对该页的支持。第二页允许用户基于日期执行查询。

本演练演示以下任务:

  • 创建由以下两个项目构成的 Silverlight 业务应用程序:Silverlight 客户端和 ASP.NET Web 应用程序。

  • 通过修改资源字符串更改应用程序名称。

  • 基于数据库文件创建一个实体数据模型。

  • 创建一个域服务,该服务向 Silverlight 客户端公开实体数据模型中的数据。有关更多信息,请参见域服务

  • 修改和添加针对域服务的自定义查询。

  • 创建附加 Silverlight 页以便向用户提供数据。

  • 将按钮添加到默认导航栏以便访问 Silverlight 页。

  • 对 Silverlight 页进行配置,以便通过将项从**“数据源”**窗口拖放到 Silverlight 设计器来显示数据。

  • 对数据进行排序和分页。

  • 配置用户界面以便使用查询参数。

必备条件

除 WCF RIA Services 和 WCF RIA Services 工具包之外,本演练和 WCF RIA Services 文档中提供的其他演练还要求正确安装和配置 Visual Studio 2010 和 Silverlight Developer 运行时及 SDK 等必备程序。它们还要求安装和配置具有高级服务的 SQL Server 2008 R2 Express 以及安装 AdventureWorks OLTP 和 LT 数据库。

WCF RIA Services 的必备条件节点中的主题提供有关如何满足这些前提条件的详细说明。在继续本演练之前,请按照此处提供的说明执行操作,以确保您在执行本 RIA Services 演练时尽可能少地遇到问题。

本演练假设您可以创建一个 Silverlight 业务应用程序。在演练:使用“Silverlight 业务应用程序”模板中介绍完成此任务的过程。

创建 Silverlight 业务应用程序

Silverlight 业务应用程序是具有两个项目的解决方案:一个 Silverlight 应用程序和一个承载该 Silverlight 应用程序的 ASP.NET Web 应用程序。Silverlight 业务应用程序具有内置功能。默认情况下,它们有一个主页、一个“关于”页、一个导航栏和站点注册功能。此外还提供了一个默认应用程序名称来作为资源字符串,您可以将该资源字符串更改为您的应用程序名称。

创建应用程序

  1. 在 Visual Studio 2010 中,在 Visual Basic 或 C# 中创建一个名为 AdventureWorksApp 的新 Silverlight 业务应用程序项目。在演练:使用“Silverlight 业务应用程序”模板中介绍完成此任务的过程。

    AdventureWorksApp 解决方案用两个项目创建:一个 AdventureWorksApp Silverlight 项目和一个 AdventureWorksApp.Web Web 应用程序项目。

  2. 在**“解决方案资源管理器”**中,展开 AdventureWorksApp 项目。

  3. 展开 Assets 文件夹,然后展开 Resources。

  4. 双击 ApplicationStrings.resx 以便打开资源设计器。

  5. ApplicationName 资源字符串**“值”**更改为 Adventure Works Application

  6. 保存更改并关闭 ApplicationStrings.resx 文件。

  7. 运行该应用程序。

    主页将打开并且显示默认设计,其中包含更新的应用程序名称。

为应用程序创建数据模型

为了在该应用程序中管理数据,您使用实体数据模型。

创建实体数据模型

  1. 在**“解决方案资源管理器”中右击 AdventureWorksApp.Web,然后单击“添加”,再单击“新建项”**。

    此时将出现**“添加新项”**对话框。

  2. 在**“数据”类别中,单击“ADO.NET 实体数据模型”**。

    RIADisplayingData01EDMX

  3. 将名称更改为 AdventureWorksEDM.edmx,然后单击**“添加”**。

    **“实体数据模型向导”**将打开。

  4. 在**“选择模型内容”页上,单击“从数据库生成”,然后单击“下一步”**。

  5. 在**“选择您的数据连接”页上,单击“新建连接”**。

    此时出现**“连接属性”**对话框。

  6. 为数据源选择“Microsoft SQL Server 数据库文件”,然后指定 AdventureWorksLT 数据库文件的位置。

  7. 单击**“确定”**。

  8. 在**“选择您的数据连接”页上,单击“下一步”**。

  9. 如果出现一条消息,请求您将数据库文件复制到您的项目中并修改连接,则单击**“是”**。

  10. 在**“选择数据库对象”页上,展开“表”**节点。

  11. 选中**“SalesOrderHeader (Sales LT)”**表旁的复选框。

  12. 单击**“完成”**。

    SalesOrderHeader 表将显示在实体设计器中。

  13. 生成解决方案。

    您必须在添加域服务之前生成解决方案。

创建域服务

域服务向客户端公开数据模型中的数据实体和操作。在此过程中,您将向服务器项目添加一个域服务。

创建域服务

  1. 在**“解决方案资源管理器”中右击 AdventureWorksApp.Web,然后单击“添加”,再单击“新建项”**。

    此时将出现**“添加新项”**对话框。

  2. 在**“Web”类别中,单击“域服务类”**模板。

  3. 将域服务类命名为 AdventureWorksService,然后单击**“添加”**。

    此时将打开**“添加新的域服务类”**对话框。

  4. 选中**“SalesOrderHeader”“启用编辑”复选框,然后单击“确定”**。

    RIADisplayingData02AddNewDomainServiceClass

  5. 生成解决方案。

更改域服务查询

在您添加某一域服务类时,该类将用查询方法填充。您可以决定不进一步修改就使用这些查询方法。但在许多情况下,需要进行一些修改。在此过程中,您将编辑 GetSalesOrderHeaders 查询方法。

更改域服务查询

  1. 在**“解决方案资源管理器”**中,双击 AdventureWorksService.vb 或 AdventureWorksService.cs 以便打开该文件。

  2. 如下面的代码所示,更新 GetSalesOrderHeaders 方法。

    Public Function GetSalesOrderHeaders() As IQueryable(Of SalesOrderHeader)
        Return Me.ObjectContext.SalesOrderHeaders.OrderBy(Function(e) e.SalesOrderID)
    End Function
    
    public IQueryable<SalesOrderHeader> GetSalesOrderHeaders()
    {
        return this.ObjectContext.SalesOrderHeaders.OrderBy(e=>e.SalesOrderID);
    }
    
  3. 生成解决方案。

创建 Silverlight 页以显示数据

在此过程中,您将添加一个 OrderList 页,以显示来自 SalesOrderHeader 表的数据。

创建 Silverlight 页

  1. 在**“解决方案资源管理器”的 AdventureWorksApp 项目中右击“视图”**文件夹,然后添加一个新项。

  2. 在**“添加新项”对话框中,选择“Silverlight”类别,然后单击“Silverlight 页”**模板。

  3. 将名称更改为 OrderList.xaml,然后单击**“添加”**。

    OrderList.xaml 即在设计器中打开。

  4. 从工具箱中,将**“TextBlock”**拖到设计器的顶部。

  5. 在“属性”窗口中,将**“Text”**属性更改为 Order List

  6. 保存该 OrderList.xaml 页。

向主页添加导航按钮

在此过程中,您向该应用程序的主页添加一个用于导航到 OrderList 页的按钮。

创建导航按钮

  1. 在**“解决方案资源管理器”**中双击 MainPage.xaml,以便在设计器中打开它。

  2. 在 XAML 视图中,在 <HyperlinkButton x:Name="Link2" ... /> 行之后添加以下标记。

    <Rectangle x:Name="Divider3" Style="{StaticResource DividerStyle}"/>
    <HyperlinkButton x:Name="Link3" Content="Order List" Style="{StaticResource LinkStyle}" NavigateUri="/OrderList" TargetName="ContentFrame"/>
    
  3. 运行该应用程序。

    **“Order List”**按钮应该在导航栏中出现。

  4. 单击**“Order List”**按钮。

    此时将出现 OrderList 页。

在 OrderList 页上显示订单数据

在此过程中,您创建并配置 DataGrid,以便通过将订单实体从**“数据源”**窗口拖到设计器,显示订单数据。

创建数据绑定的 DataGrid

  1. 在**“解决方案资源管理器”**中,双击 OrderList.xaml。

  2. 单击**“数据”菜单,然后单击“显示数据源”**。

    此时**“数据源”窗口将打开。请注意,该“数据源”**窗口已包含可用于该应用程序的实体。

  3. 从**“数据源”窗口中,将“SalesOrderHeader”**节点拖到设计器(在 Order List 文本块之下)。

    用来自 SalesOrderHeader 表的列标题填充的**“DataGrid”**将出现在设计图面上。

    RIADisplayingData03OrderListPageWithDataGrid

  4. 运行该应用程序。

  5. 在导航栏中,单击**“Order List”**按钮。

    订单数据将显示在“Order List”页中。

    RIADisplayingData04OrderListPageWithDataGridComple

向域服务添加自定义查询

您可以在域服务中创建附加的查询。此过程添加两个自定义查询。

向域服务添加自定义查询

  1. 在**“解决方案资源管理器”**中,双击 AdventureWorksService.vb 或 AdventureWorksService.cs。

  2. 将下面的方法添加到 AdventureWorksService 类中:

    Public Function GetOrdersWithSmallSubtotals() As IQueryable(Of SalesOrderHeader)
        Return Me.ObjectContext.SalesOrderHeaders.Where(Function(p) p.SubTotal <= 2000).OrderBy(Function(p) p.SubTotal)
    End Function
    
    Public Function GetShipDateBefore(ByVal shipDate As DateTime) As IQueryable(Of SalesOrderHeader)
        Return Me.ObjectContext.SalesOrderHeaders.Where(Function(p) p.ShipDate < shipDate).OrderBy(Function(p) p.SalesOrderID)
    End Function
    
    public IQueryable<SalesOrderHeader> GetOrdersWithSmallSubtotals()
    {
        return this.ObjectContext.SalesOrderHeaders.Where(e => e.SubTotal <= 2000).OrderBy(e => e.SubTotal);
    }
    
    public IQueryable<SalesOrderHeader> GetShipDateBefore(DateTime shipDate)
    {
        return this.ObjectContext.SalesOrderHeaders.Where(e => e.ShipDate < shipDate).OrderBy(e => e.SalesOrderID);
    }
    
  3. 如果您正在使用 Visual Basic,则在 AdventureWorksService.vb 文件的顶部,将 Option Strict 语句设置为 Off

  4. 生成解决方案。

显示来自自定义查询的数据

在此过程中,通过在**“数据源”窗口中选择新查询,然后将其拖到已处于设计器中的“DataGrid”上,显示来自该查询的数据。此操作将重新配置“DataGrid”**的绑定以便显示来自所选查询的数据。

在现有 DataGrid 中显示来自自定义查询的数据

  1. 在**“解决方案资源管理器”**中,双击 OrderList.xaml。

  2. 在**“数据源”窗口中,单击“SalesOrderHeader”**,然后单击下拉菜单。

    RIADisplayingData05QueriesInDataSources

    请注意在该菜单的底部列出的三个查询。选中的查询是在将此实体拖放到设计器后将在生成的数据源的 QueryName 中设置的查询。

  3. 从查询列表中选择**“GetOrdersWithSmallSubtotalsQuery”**,以便将它设置为此实体的查询。

  4. 将**“SalesOrderHeader”节点拖到设计器上的现有“DataGrid”** 中。

  5. 运行该应用程序。

  6. 单击**“Order List”**按钮。

    请注意,在**“DataGrid”**中列出的订单小计未超出 2000。

    RIADisplayingData06SmallSubtotalsQueryResult

添加排序

除了在基础查询中使用 OrderBy 子句对数据进行排序之外,您还可以在您的页面的 XAML 中配置排序。您通过将 SortDescriptors 添加到 DomainDataSource 来配置排序。您可以直接在 XAML 中添加 SortDescriptors,也可以使用**“属性”**窗口进行添加,如以下过程中所示。

使用“属性”窗口添加 SortDescriptors

  1. 在**“解决方案资源管理器”**中,双击 OrderList.xaml。

  2. 在 XAML 视图中,将鼠标光标放置于其 Name 特性设置为 salesOrderHeaderDomainDataSource1riaControls:DomainDataSource 元素中。

    Warning 警告:
    在该文件中存在两个 riaControls:DomainDataSource 元素。请确保将您的鼠标光标放置于其 Name 特性设置为 salesOrderHeaderDomainDataSource1 的元素中。
  3. 在**“属性”窗口中,单击“SortDescriptors”属性,然后单击省略号按钮 (…**)。

    RIADisplayingData07SortDescriptorsProperty

    此时将出现 SortDescriptors 集合编辑器。

  4. 单击**“添加”**。

    SortDescriptors 项将被添加。

  5. 在**“属性”下,展开“其他”**类别。

  6. 在**“PropertyPath”**值列中,键入 CustomerID

  7. 单击**“确定”**。

    请注意,以下 XAML 已添加到 riaControls:DomainDataSource 元素中:

    <riaControls:DomainDataSource.SortDescriptors>
        <riaControls:SortDescriptor PropertyPath="CustomerID" />
    </riaControls:DomainDataSource.SortDescriptors>
    
  8. 运行该应用程序。

  9. 单击**“Order List”**按钮。

    请注意,数据将按列表客户 ID 排序。

    RIADisplayingData09SortedByCustomerID

    Warning 警告:
    同时实现分页和排序时,至少包含一个 SortDescriptor,将其 PropertyPath 特性分配给包含唯一值(如主键)的属性。或者将基于包含唯一值的属性的 OrderBy 子句添加到 DomainDataSource 中的查询。如果仅对不包含唯一值的属性排序数据,返回值可能包含不一致的数据或缺少跨页数据。

添加分页

在此过程中,您通过将 DataPager 添加到数据源来添加分页。您将 DataPager.Source 设置为 DomainDataSource,它管理页导航应该控制的数据。

配置数据的分页

  1. 在**“解决方案资源管理器”**中,双击 OrderList.xaml。

  2. 在工具箱中,找到 DataPager 控件。

  3. 将**“DataPager”**拖到设计器中 DataGrid 下方的区域。

  4. 在**“数据源”窗口中,单击“SalesOrderHeader”节点,单击下拉菜单,并确认选择了“GetOrdersWithSmallSubtotalsQuery”**。

  5. 将**“SalesOrderHeader”节点拖到“DataPager”**上。

    这会将 DataPager 的 Source 属性设置为正确的数据源。

  6. 在设计器上选择 DataPager

  7. 在**“属性”窗口中,将“PageSize”**属性设置为 5。

  8. 运行该应用程序。

  9. 单击**“Order List”**按钮。

  10. DataPager 上单击导航按钮,以便在 DataGrid 中一次导航 5 个记录。

    RIADisplayingData10OrderListPageComplete

创建按日期搜索订单的页面

在本演练的前面部分,您向域服务添加了一个自定义查询,该查询返回其发货日期在用户提供的日期之前的订单。此过程演示如何使用**“数据源”**窗口创建一个用户界面,该用户界面将采用用户提供的参数,这些参数将传递到域服务查询。

创建用户界面

  1. 在 AdventureWorksApp 项目的**“Views”**文件夹中,添加名为 OrderSearchByShipDateBefore.xaml 的一个新的 Silverlight 页。

  2. 在**“解决方案资源管理器”**中,双击 MainPage.xaml

  3. 在 XAML 视图中,在 <HyperlinkButton x:Name="Link3" ... /> 行之后添加以下代码。

    <Rectangle x:Name="Divider4" Style="{StaticResource DividerStyle}"/>
    <HyperlinkButton x:Name="Link4" Content="Ship Date" Style="{StaticResource LinkStyle}" NavigateUri="/OrderSearchByShipDateBefore" TargetName="ContentFrame"/>
    
  4. 在**“解决方案资源管理器”**中,双击 OrderSearchByShipDateBefore.xaml。

  5. 在**“数据源”窗口中,单击“SalesOrderHeader”**节点,然后单击下拉菜单。

  6. 选择**“GetShipDateBeforeQuery”**,将它设置为此实体的查询。

    RIADisplayingData11DataSourcesGetShipDateBeforeQue

  7. 将**“SalesOrderHeader”**节点拖到设计器上。

    除了 DataGrid 之外,还创建一个文本框以便接受查询中的参数,并且添加了一个按钮以便运行查询和加载数据。

    RIADisplayingData12ShipDateQueryOnDesigner

测试应用程序

在此过程中,您将生成并运行该应用程序,以便确认该应用程序的行为符合预期。

测试应用程序

  1. 在**“生成”菜单上单击“生成解决方案”**。

    验证解决方案将生成且没有错误。

  2. 运行该应用程序。

  3. 单击**“发货日期”**按钮以便使用发货日期查询打开该页。

  4. 在**“发货日期”**框中键入某一日期,例如 1/1/2006

  5. 单击**“加载”**。

    请注意,将只返回指定日期之前的发货日期。

    RIADisplayingData13ShipDateQueryComplete

  6. 请尝试其他发货日期。

后续步骤

完成本演练后,您可以执行以下相关任务:

另请参见

概念

Silverlight 客户端