演练:将 WPF 控件绑定到 WCF 数据服务

在本演练中,您将创建一个包含数据绑定控件的 WPF 应用程序。 这些控件将绑定到在 WCF 数据服务中封装的客户记录。 您还将添加客户可用于查看和更新记录的按钮。

本演练阐释了以下任务:

  • 创建一个利用 AdventureWorksLT 示例数据库中的数据生成的实体数据模型。

  • 创建一个向 WPF 应用程序公开实体数据模型中的数据的 WCF 数据服务。

  • 通过将项从**“数据源”**窗口拖到 WPF 设计器来创建一组数据绑定控件。

  • 创建用于向前/向后浏览客户记录的按钮。

  • 创建一个用于将控件中数据的更改保存到 WCF 数据服务和基础数据源中的按钮。

    提示

    以下说明中的某些 Visual Studio 用户界面元素在计算机上出现的名称或位置可能会不同。 您安装的 Visual Studio 版本以及使用的设置决定了这些元素。 有关更多信息,请参见 使用设置

系统必备

您需要以下组件来完成本演练:

  • Visual Studio 2010.

  • 对附加了 AdventureWorksLT 示例数据库的 SQL Server 或 SQL Server Express 的正在运行的实例的访问权限。 您可以从 CodePlex 网站下载 AdventureWorksLT 数据库。

事先了解以下概念也很有用,但对于完成本演练并不是必需的:

创建服务项目

从为 WCF 数据服务创建项目开始本演练:

创建服务项目

  1. 启动 Visual Studio。

  2. 在**“文件”菜单上指向“新建”,再单击“项目”**。

  3. 展开**“Visual C#”“Visual Basic”,然后选择“Web”**。

  4. 选择**“ASP.NET Web 应用程序”**项目模板。

  5. 在**“名称”框中键入 AdventureWorksService,然后单击“确定”**。

    Visual Studio 将创建 AdventureWorksService 项目。

  6. 在**“解决方案资源管理器”中右击“Default.aspx”,然后选择“删除”**。 本演练中不需要此文件。

为服务创建实体数据模型

若要通过使用 WCF 数据服务向应用程序公开数据,则必须为该服务定义一个数据模型。 WCF 数据服务支持两种类型的数据模型:实体数据模型和自定义数据模型,这两种数据模型是通过使用实现 IQueryable<T> 接口的公共语言运行时 (CLR) 对象定义的。 在本演练中,您将为该数据模型创建一个实体数据模型。

创建实体数据模型

  1. 在**“项目”菜单上,单击“添加新项”**。

  2. 选择**“ADO.NET 实体数据模型”**项目项。

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

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

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

  5. 在**“选择您的数据连接”**页上,选择下列选项之一:

    • 如果下拉列表中包含到 AdventureWorksLT 示例数据库的数据连接,请选择该连接。

      - 或 -

    • 单击**“新建连接”**并创建到 AdventureWorksLT 数据库的连接。

  6. 在**“选择您的数据连接”页上,确保选中了“将 App.Config 中的实体连接设置另存为”选项,然后单击“下一步”**。

  7. 在**“选择数据库对象”页上,展开“表”,然后选择“SalesOrderHeader”**表。

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

创建服务

创建 WCF 数据服务,以向 WPF 应用程序公开实体数据模型中的数据。

创建服务

  1. 在**“项目”菜单上选择“添加新项”**。

  2. 选择**“WCF 数据服务”**项目项。

  3. 在**“名称”框中键入 AdventureWorksService.svc,然后单击“添加”**。

    Visual Studio 将 AdventureWorksService.svc 添加到项目中。

配置服务

若要操作所创建的实体数据模型,您必须对服务进行配置。

配置服务

  1. 在 AdventureWorks.svc 代码文件中,用下面的代码替换 AdventureWorksService 类声明。

    Public Class AdventureWorksService
        Inherits DataService(Of AdventureWorksLTEntities)
    
        ' This method is called only once to initialize service-wide policies.
        Public Shared Sub InitializeService(ByVal config As IDataServiceConfiguration)
            config.SetEntitySetAccessRule("SalesOrderHeaders", EntitySetRights.All)
            config.UseVerboseErrors = True
        End Sub
    End Class
    
    public class AdventureWorksService : DataService<AdventureWorksLTEntities>
    {
        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(IDataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("SalesOrderHeaders", EntitySetRights.All);
        }
    }
    

    此代码将更新 AdventureWorksService 类,以使其从操作实体数据模型中的 AdventureWorksLTEntities 对象上下文类的 DataService<T> 派生。 此代码还将更新 InitializeService 方法,以使服务的客户端具有对 SalesOrderHeader 实体的完全读/写访问权限。

    有关 ADO.NET Entity Framework 中的对象上下文类的更多信息,请参见Object Services Overview (Entity Framework)

  2. 生成项目,并确认生成过程中未发生错误。

创建 WPF 客户端应用程序

若要显示 WCF 数据服务中的数据,请使用基于该服务的数据源创建一个新的 WPF 应用程序。 在本演练后面的部分中,您将向该应用程序中添加数据绑定控件。

创建 WPF 客户端应用程序

  1. 在**“解决方案资源管理器”中,右击解决方案节点,单击“添加”,然后选择“新建项目”**。

    提示

    在 Visual Basic 项目中,仅当在“选项”对话框 ->“项目和解决方案”->“常规”中选中“总是显示解决方案”复选框时,解决方案节点才会出现在“解决方案资源管理器”中。

  2. 在**“新建类型”对话框中,展开“Visual C#”“Visual Basic”,然后选择“Windows”**。

  3. 选择**“WPF 应用程序”**项目模板。

  4. 在**“名称”框中键入 AdventureWorksSalesEditor,然后单击“确定”**。

    Visual Studio 将 AdventureWorksSalesEditor 项目添加到解决方案中。

  5. 在**“数据”菜单上,单击“显示数据源”**。

    将打开**“数据源”**窗口。

  6. 在**“数据源”窗口中,单击“添加新数据源”**。

    **“数据源配置向导”**打开。

  7. 在该向导的**“选择数据源类型”页上,选择“服务”,然后单击“下一步”**。

  8. 在**“添加服务引用”对话框中,单击“发现”**。

    Visual Studio 将在当前解决方案中搜索可用服务,并将 AdventureWorksService.svc 添加到**“服务”**框中的可用服务列表中。

  9. 在**“命名空间”**框中,键入 AdventureWorksService。

  10. 在**“服务”框中,单击 AdventureWorksService.svc,再单击“确定”**。

    Visual Studio 将下载该服务信息,然后返回到**“数据源配置向导”**。

  11. 在**“添加服务引用”页上,单击“完成”**。

    Visual Studio 将表示该服务返回的数据的节点添加到**“数据源”**窗口中。

定义窗口的用户界面

通过在 WPF 设计器中修改 XAML,向窗口中添加若干按钮。 在本演练后面的部分中,您将添加可让用户通过这些按钮来查看和更新销售记录的代码。

创建窗口布局

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

    将在 WPF 设计器中打开相应的窗口。

  2. 在设计器的 XAML 视图中,在 <Grid> 标记之间添加以下代码:

    <Grid.RowDefinitions>
        <RowDefinition Height="75" />
        <RowDefinition Height="525" />
    </Grid.RowDefinitions>
    <Button HorizontalAlignment="Left" Margin="22,20,0,24" Name="backButton" Width="75">&lt;</Button>
    <Button HorizontalAlignment="Left" Margin="116,20,0,24" Name="nextButton" Width="75">&gt;</Button>
    <Button HorizontalAlignment="Right" Margin="0,21,46,24" Name="saveButton" Width="110">Save changes</Button>
    
  3. 生成项目。

创建数据绑定控件

通过将 SalesOrderHeaders 节点从**“数据源”**窗口拖动到设计器中,创建显示客户记录的控件。

创建数据绑定控件

  1. 在**“数据源”窗口中,单击“SalesOrderHeaders”节点的下拉菜单,并选择“详细信息”**。

  2. 展开**“SalesOrderHeaders”**节点。

  3. 在本示例中,由于一些字段不会显示,因此单击以下节点旁边的下拉菜单并选择**“无”**:

    • CreditCardApprovalCode

    • ModifiedDate

    • OnlineOrderFlag

    • RevisionNumber

    • rowguid

    此操作将阻止 Visual Studio 在下一步中为这些节点创建数据绑定控件。 对于本演练,假定最终用户不需要查看此数据。

  4. 从**“数据源”窗口中,将“SalesOrderHeaders”**节点拖动到包含按钮的行的下方的网格行。

    Visual Studio 将生成一些 XAML 和代码,它们将创建一组绑定到**“Product”**表中的数据的控件。 有关生成的 XAML 和代码的更多信息,请参见在 Visual Studio 中将 WPF 控件绑定到数据

  5. 在设计器中,单击**“Customer ID”(客户 ID)**标签旁边的文本框。

  6. 在**“属性”窗口中,选中“IsReadOnly”**属性旁边的复选框。

  7. 设置以下每个文本框的**“IsReadOnly”**属性:

    • “Purchase Order Number”(采购订单号)

    • “Sales Order ID”(销售订单 ID)

    • “Sales Order Number”(销售订单号)

从服务中加载数据

使用服务代理对象从服务中加载销售数据,然后将返回的数据分配给 WPF 窗口中 CollectionViewSource 的数据源。

从服务中加载数据

  1. 在设计器中,双击文本**“MainWindow”**来创建 Window_Loaded 事件处理程序。

  2. 用下面的代码替换该事件处理程序。 确保用您的开发计算机上的本地主机地址替换此代码中的 localhost 地址。

    Private DataServiceClient As AdventureWorksService.AdventureWorksLTEntities
    Private SalesQuery As System.Data.Services.Client.DataServiceQuery(Of AdventureWorksService.SalesOrderHeader)
    Private OrdersViewSource As CollectionViewSource
    
    Private Sub Window_Loaded(ByVal Sender As Object, ByVal e As RoutedEventArgs) Handles MyBase.Loaded
    
        ' TODO: Modify the port number in the following URI as required.
        DataServiceClient = New AdventureWorksService.AdventureWorksLTEntities( _
        New Uri("https://localhost:32415/AdventureWorksService.svc"))
        SalesQuery = DataServiceClient.SalesOrderHeaders
    
        OrdersViewSource = CType(Me.FindResource("SalesOrderHeadersViewSource"), CollectionViewSource)
        OrdersViewSource.Source = SalesQuery.Execute()
        OrdersViewSource.View.MoveCurrentToFirst()
    End Sub
    
    private AdventureWorksService.AdventureWorksLTEntities dataServiceClient;
    private System.Data.Services.Client.DataServiceQuery<AdventureWorksService.SalesOrderHeader> salesQuery;
    private CollectionViewSource ordersViewSource;
    
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        // TODO: Modify the port number in the following URI as required.
        dataServiceClient = new AdventureWorksService.AdventureWorksLTEntities(
            new Uri("https://localhost:45899/AdventureWorksService.svc"));
        salesQuery = dataServiceClient.SalesOrderHeaders;
    
        ordersViewSource = ((CollectionViewSource)(this.FindResource("salesOrderHeadersViewSource")));
        ordersViewSource.Source = salesQuery.Execute();
        ordersViewSource.View.MoveCurrentToFirst();
    }
    

导航销售记录

添加可让客户通过**“<”“>”**按钮来浏览销售记录的代码。

使用户能够导航销售记录

  1. 在设计器中,双击窗口图面上的**“<”**按钮。

    Visual Studio 将打开代码隐藏文件,并为 Click 事件创建新的 backButton_Click 事件处理程序。

  2. 用下面的代码替换生成的 backButton_Click 事件处理程序:

    If OrdersViewSource.View.CurrentPosition > 0 Then
        OrdersViewSource.View.MoveCurrentToPrevious()
    End If
    
    if (ordersViewSource.View.CurrentPosition > 0)
        ordersViewSource.View.MoveCurrentToPrevious();
    
  3. 返回到设计器,并双击 > 按钮。

    Visual Studio 将打开代码隐藏文件,并为 Click 事件创建新的 nextButton_Click 事件处理程序。

  4. 用下面的代码替换生成的 nextButton_Click 事件处理程序。

    If OrdersViewSource.View.CurrentPosition < CType(OrdersViewSource.View, CollectionView).Count - 1 Then
        OrdersViewSource.View.MoveCurrentToNext()
    End If
    
    if (ordersViewSource.View.CurrentPosition < ((CollectionView)ordersViewSource.View).Count - 1)
    {
        ordersViewSource.View.MoveCurrentToNext();
    }
    

保存对销售记录所做的更改

添加可让用户通过**“Save changes”(保存更改)**按钮来查看和保存对销售记录所做的更改的代码。

添加保存对销售记录所做更改的功能

  1. 在设计器中双击**“Save changes”(保存更改)**按钮。

    Visual Studio 将打开代码隐藏文件,并为 Click 事件创建新的 saveButton_Click 事件处理程序。

  2. 将下面的代码添加到 saveButton_Click 事件处理程序中。

    Dim CurrentOrder As AdventureWorksService.SalesOrderHeader = CType(OrdersViewSource.View.CurrentItem, AdventureWorksService.SalesOrderHeader)
    
    DataServiceClient.UpdateObject(CurrentOrder)
    DataServiceClient.SaveChanges()
    
    AdventureWorksService.SalesOrderHeader currentOrder = (AdventureWorksService.SalesOrderHeader)ordersViewSource.View.CurrentItem;
    dataServiceClient.UpdateObject(currentOrder);
    dataServiceClient.SaveChanges();
    

测试应用程序

生成并运行应用程序,以确认您能够查看和更新客户记录。

测试应用程序

  1. 在**“生成”菜单上,单击“生成解决方案”**。 验证解决方案已生成且未发生错误。

  2. 按 Ctrl+F5。

    Visual Studio 将启动 AdventureWorksService 项目,但不对其进行调试。

  3. 在**“解决方案资源管理器”中,右击“AdventureWorksSalesEditor”**项目。

  4. 在上下文菜单上的**“调试”下,单击“启动新实例”**。

    将运行应用程序。 确认以下事项:

    • 文本框显示的是销售订单 ID 为**“71774”**的第一条销售记录中的数据的不同字段。

    • 可以单击**“>”“<”**按钮来浏览其他销售记录。

  5. 在某条销售记录中,在**“Comment”(注释)框中键入一些文本,再单击“Save changes”(保存更改)**。

  6. 关闭应用程序,然后从 Visual Studio 再次启动应用程序。

  7. 导航到所更改的销售记录,确认相关更改在您关闭并重新打开应用程序后得以保留。

  8. 关闭应用程序。

后续步骤

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

请参见

任务

如何:在 Visual Studio 中将 WPF 控件绑定到数据

演练:将 WPF 控件绑定到实体数据模型

演练:将 WPF 控件绑定到数据集

概念

在 Visual Studio 中将 WPF 控件绑定到数据

WPF and Silverlight Designer 概述

数据绑定概述

其他资源

ADO.NET Data Services Framework Overview

Data Model

Entity Data Model

Introducing the Entity Framework