演练:将 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 数据服务。 有关更多信息,请参见 ADO.NET Data Services Framework Overview。
WCF 数据服务中的数据模型。 有关更多信息,请参见Data Model。
实体数据模型和 ADO.NET Entity Framework。 有关更多信息,请参见Entity Data Model和Introducing the Entity Framework。
使用 WPF 设计器。 有关更多信息,请参见 WPF and Silverlight Designer 概述。
WPF 数据绑定。 有关更多信息,请参见数据绑定概述。
创建服务项目
从为 WCF 数据服务创建项目开始本演练:
创建服务项目
启动 Visual Studio。
在**“文件”菜单上指向“新建”,再单击“项目”**。
展开**“Visual C#”或“Visual Basic”,然后选择“Web”**。
选择**“ASP.NET Web 应用程序”**项目模板。
在**“名称”框中键入 AdventureWorksService,然后单击“确定”**。
Visual Studio 将创建 AdventureWorksService 项目。
在**“解决方案资源管理器”中右击“Default.aspx”,然后选择“删除”**。 本演练中不需要此文件。
为服务创建实体数据模型
若要通过使用 WCF 数据服务向应用程序公开数据,则必须为该服务定义一个数据模型。 WCF 数据服务支持两种类型的数据模型:实体数据模型和自定义数据模型,这两种数据模型是通过使用实现 IQueryable<T> 接口的公共语言运行时 (CLR) 对象定义的。 在本演练中,您将为该数据模型创建一个实体数据模型。
创建实体数据模型
在**“项目”菜单上,单击“添加新项”**。
选择**“ADO.NET 实体数据模型”**项目项。
将名称更改为 AdventureWorksModel.edmx,然后单击**“添加”**。
**“实体数据模型向导”**将打开。
在**“选择模型内容”页上,单击“从数据库生成”,然后单击“下一步”**。
在**“选择您的数据连接”**页上,选择下列选项之一:
如果下拉列表中包含到 AdventureWorksLT 示例数据库的数据连接,请选择该连接。
- 或 -
单击**“新建连接”**并创建到 AdventureWorksLT 数据库的连接。
在**“选择您的数据连接”页上,确保选中了“将 App.Config 中的实体连接设置另存为”选项,然后单击“下一步”**。
在**“选择数据库对象”页上,展开“表”,然后选择“SalesOrderHeader”**表。
单击**“完成”**。
创建服务
创建 WCF 数据服务,以向 WPF 应用程序公开实体数据模型中的数据。
创建服务
在**“项目”菜单上选择“添加新项”**。
选择**“WCF 数据服务”**项目项。
在**“名称”框中键入 AdventureWorksService.svc,然后单击“添加”**。
Visual Studio 将 AdventureWorksService.svc 添加到项目中。
配置服务
若要操作所创建的实体数据模型,您必须对服务进行配置。
配置服务
在 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)。
生成项目,并确认生成过程中未发生错误。
创建 WPF 客户端应用程序
若要显示 WCF 数据服务中的数据,请使用基于该服务的数据源创建一个新的 WPF 应用程序。 在本演练后面的部分中,您将向该应用程序中添加数据绑定控件。
创建 WPF 客户端应用程序
在**“解决方案资源管理器”中,右击解决方案节点,单击“添加”,然后选择“新建项目”**。
提示
在 Visual Basic 项目中,仅当在“选项”对话框 ->“项目和解决方案”->“常规”中选中“总是显示解决方案”复选框时,解决方案节点才会出现在“解决方案资源管理器”中。
在**“新建类型”对话框中,展开“Visual C#”或“Visual Basic”,然后选择“Windows”**。
选择**“WPF 应用程序”**项目模板。
在**“名称”框中键入 AdventureWorksSalesEditor,然后单击“确定”**。
Visual Studio 将 AdventureWorksSalesEditor 项目添加到解决方案中。
在**“数据”菜单上,单击“显示数据源”**。
将打开**“数据源”**窗口。
在**“数据源”窗口中,单击“添加新数据源”**。
**“数据源配置向导”**打开。
在该向导的**“选择数据源类型”页上,选择“服务”,然后单击“下一步”**。
在**“添加服务引用”对话框中,单击“发现”**。
Visual Studio 将在当前解决方案中搜索可用服务,并将 AdventureWorksService.svc 添加到**“服务”**框中的可用服务列表中。
在**“命名空间”**框中,键入 AdventureWorksService。
在**“服务”框中,单击 AdventureWorksService.svc,再单击“确定”**。
Visual Studio 将下载该服务信息,然后返回到**“数据源配置向导”**。
在**“添加服务引用”页上,单击“完成”**。
Visual Studio 将表示该服务返回的数据的节点添加到**“数据源”**窗口中。
定义窗口的用户界面
通过在 WPF 设计器中修改 XAML,向窗口中添加若干按钮。 在本演练后面的部分中,您将添加可让用户通过这些按钮来查看和更新销售记录的代码。
创建窗口布局
在**“解决方案资源管理器”**中,双击 MainWindow.xaml。
将在 WPF 设计器中打开相应的窗口。
在设计器的 XAML 视图中,在 <Grid> 标记之间添加以下代码:
<Grid.RowDefinitions> <RowDefinition Height="75" /> <RowDefinition Height="525" /> </Grid.RowDefinitions> <Button HorizontalAlignment="Left" Margin="22,20,0,24" Name="backButton" Width="75"><</Button> <Button HorizontalAlignment="Left" Margin="116,20,0,24" Name="nextButton" Width="75">></Button> <Button HorizontalAlignment="Right" Margin="0,21,46,24" Name="saveButton" Width="110">Save changes</Button>
生成项目。
创建数据绑定控件
通过将 SalesOrderHeaders 节点从**“数据源”**窗口拖动到设计器中,创建显示客户记录的控件。
创建数据绑定控件
在**“数据源”窗口中,单击“SalesOrderHeaders”节点的下拉菜单,并选择“详细信息”**。
展开**“SalesOrderHeaders”**节点。
在本示例中,由于一些字段不会显示,因此单击以下节点旁边的下拉菜单并选择**“无”**:
CreditCardApprovalCode
ModifiedDate
OnlineOrderFlag
RevisionNumber
rowguid
此操作将阻止 Visual Studio 在下一步中为这些节点创建数据绑定控件。 对于本演练,假定最终用户不需要查看此数据。
从**“数据源”窗口中,将“SalesOrderHeaders”**节点拖动到包含按钮的行的下方的网格行。
Visual Studio 将生成一些 XAML 和代码,它们将创建一组绑定到**“Product”**表中的数据的控件。 有关生成的 XAML 和代码的更多信息,请参见在 Visual Studio 中将 WPF 控件绑定到数据。
在设计器中,单击**“Customer ID”(客户 ID)**标签旁边的文本框。
在**“属性”窗口中,选中“IsReadOnly”**属性旁边的复选框。
设置以下每个文本框的**“IsReadOnly”**属性:
“Purchase Order Number”(采购订单号)
“Sales Order ID”(销售订单 ID)
“Sales Order Number”(销售订单号)
从服务中加载数据
使用服务代理对象从服务中加载销售数据,然后将返回的数据分配给 WPF 窗口中 CollectionViewSource 的数据源。
从服务中加载数据
在设计器中,双击文本**“MainWindow”**来创建 Window_Loaded 事件处理程序。
用下面的代码替换该事件处理程序。 确保用您的开发计算机上的本地主机地址替换此代码中的 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(); }
导航销售记录
添加可让客户通过**“<”和“>”**按钮来浏览销售记录的代码。
使用户能够导航销售记录
在设计器中,双击窗口图面上的**“<”**按钮。
Visual Studio 将打开代码隐藏文件,并为 Click 事件创建新的 backButton_Click 事件处理程序。
用下面的代码替换生成的 backButton_Click 事件处理程序:
If OrdersViewSource.View.CurrentPosition > 0 Then OrdersViewSource.View.MoveCurrentToPrevious() End If
if (ordersViewSource.View.CurrentPosition > 0) ordersViewSource.View.MoveCurrentToPrevious();
返回到设计器,并双击 > 按钮。
Visual Studio 将打开代码隐藏文件,并为 Click 事件创建新的 nextButton_Click 事件处理程序。
用下面的代码替换生成的 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”(保存更改)**按钮来查看和保存对销售记录所做的更改的代码。
添加保存对销售记录所做更改的功能
在设计器中双击**“Save changes”(保存更改)**按钮。
Visual Studio 将打开代码隐藏文件,并为 Click 事件创建新的 saveButton_Click 事件处理程序。
将下面的代码添加到 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();
测试应用程序
生成并运行应用程序,以确认您能够查看和更新客户记录。
测试应用程序
在**“生成”菜单上,单击“生成解决方案”**。 验证解决方案已生成且未发生错误。
按 Ctrl+F5。
Visual Studio 将启动 AdventureWorksService 项目,但不对其进行调试。
在**“解决方案资源管理器”中,右击“AdventureWorksSalesEditor”**项目。
在上下文菜单上的**“调试”下,单击“启动新实例”**。
将运行应用程序。 确认以下事项:
文本框显示的是销售订单 ID 为**“71774”**的第一条销售记录中的数据的不同字段。
可以单击**“>”或“<”**按钮来浏览其他销售记录。
在某条销售记录中,在**“Comment”(注释)框中键入一些文本,再单击“Save changes”(保存更改)**。
关闭应用程序,然后从 Visual Studio 再次启动应用程序。
导航到所更改的销售记录,确认相关更改在您关闭并重新打开应用程序后得以保留。
关闭应用程序。
后续步骤
完成本演练后,您可以执行以下相关任务:
了解如何使用 Visual Studio 中的**“数据源”**窗口将 WPF 控件绑定到其他类型的数据源。 有关更多信息,请参见演练:将 WPF 控件绑定到实体数据模型和演练:将 WPF 控件绑定到数据集。
了解如何使用 Visual Studio 中的**“数据源”**窗口来显示 WPF 控件中的相关数据(即具有父子关系的数据)。 有关更多信息,请参见演练:在 WPF 应用程序中显示相关数据。
请参见
任务
如何:在 Visual Studio 中将 WPF 控件绑定到数据
概念
在 Visual Studio 中将 WPF 控件绑定到数据
WPF and Silverlight Designer 概述