数据集和相关类是 21 世纪初的旧版 .NET 技术,使应用程序能够在应用程序与数据库断开时处理内存中的数据。 它们对于使用户能够修改数据并持续更改回数据库的应用程序特别有用。 虽然数据集已被证明是一项非常成功的技术,但我们建议新的 .NET 应用程序使用 Entity Framework Core 。 实体框架提供了一种更自然的方式来将表格数据作为对象模型,并且具有更简单的编程接口。

在本演练中,你将创建一个包含数据绑定控件的 WPF 应用程序。 这些控件将绑定到在数据集中封装的产品记录。 你还将添加用于浏览产品和保存对产品记录所做的更改的按钮。

本演练演示以下任务:

  • 创建一个 WPF 应用程序和一个利用 AdventureWorksLT 示例数据库中的数据生成的数据集。

  • 通过将数据表从“数据源”窗口拖到 WPF 设计器的窗口中,创建一组数据绑定控件

  • 创建用于向前/向后导航产品记录的按钮。

  • 创建一个用于将用户对产品记录所做的更改保存到数据表和基础数据源的按钮。

    本文中的某些 Visual Studio 用户界面元素在计算机上出现的名称或位置可能会不同。 你可能正在使用其他版本的 Visual Studio 或其他环境设置。 有关详细信息,请参阅 个性化设置 IDE

    您需要满足以下条件才能完成本演练:

  • Visual Studio

  • 对附加了 AdventureWorks Light (AdventureWorksLT) 示例数据库的 SQL Server 或 SQL Server Express 的正在运行的实例的访问权限。 若要下载数据库,请参阅 AdventureWorks 示例数据库

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

  • 数据集和 TableAdapter。 有关详细信息,请参阅 Visual Studio 中的数据集工具 TableAdapter

  • WPF 数据绑定。 有关详细信息,请参阅 数据绑定概述

    创建新的 WPF 项目以显示产品记录。

  • 打开 Visual Studio。

  • 在“开始”窗口上,选择“创建新项目” 。

  • 搜索 C#“WPF 应用”项目模板,然后按照步骤创建项目,将项目命名为“AdventureWorksProductsEditor”。

    Visual Studio 创建 AdventureWorksProductsEditor 项目。

    为应用程序创建数据集

    必须先为应用程序定义数据模型并将此模型添加到“数据源”窗口中,然后才能创建数据绑定控件 。 在本演练中,你将创建要用作数据模型的数据集。

  • “数据” 菜单上,单击 “显示数据源”

    “数据源”窗口随即打开

  • “数据源” 窗口中,单击 “添加新数据源”

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

  • 在“选择数据源类型”页上,选择“数据库”,然后单击“下一步”

  • 在“选择数据库模型”页上,选择“数据集”,然后单击“下一步”

  • 在“选择你的数据连接”页面上,选择以下选项之一

  • 如果下拉列表中包含到 AdventureWorksLT 示例数据库的数据连接,请选择该连接,然后单击“下一步”

  • 单击“新建连接”,然后创建到 AdventureWorksLT 数据库的连接

  • 在“将连接字符串保存到应用程序配置文件中”页面上,选中“是,将连接另存为”复选框,然后单击“下一步”

  • 在“选择数据库对象”页面上,展开“表”,然后选择“Product (SalesLT)”表

  • 单击“完成” 。

    Visual Studio 会将新的 AdventureWorksLTDataSet.xsd 文件添加到项目中,并将相应的“AdventureWorksLTDataSet”项添加到“数据源”窗口中。 AdventureWorksLTDataSet.xsd 文件定义了一个名为 AdventureWorksLTDataSet 的类型化数据集和一个名为 ProductTableAdapter 的 TableAdapter。 在本演练后面的部分中,你将使用 ProductTableAdapter 向数据集填充数据,并将更改保存回数据库中。

  • 生成项目。

    编辑 TableAdapter 的默认填充方法

    若要向数据集填充数据,请使用 Fill ProductTableAdapter 方法。 默认情况下, Fill 方法将向 ProductDataTable 中的 AdventureWorksLTDataSet 填充 Product 表包含的所有数据行。 你可以修改此方法以仅返回行的子集。 对于本演练而言,将修改 Fill 方法以仅返回具有照片的产品行。

  • 在“解决方案资源管理器”中,双击“AdventureWorksLTDataSet.xsd”文件

    这将打开数据集设计器。

  • 在此设计器中,右键单击“填充”、GetData() 查询,然后选择“配置”

    “TableAdapter 配置”向导随即打开

  • 在“输入 SQL 语句”页面上,在文本框中的 SELECT 语句后添加以下 WHERE 子句

    WHERE ThumbnailPhotoFileName <> 'no_image_available_small.gif'
    
  • 单击“完成” 。

    定义用户界面

    通过在 WPF 设计器中修改 XAML,将多个按钮添加到该窗口中。 在本演练后面的部分中,你将添加可让用户通过使用这些按钮来滚动和保存对产品记录所做的更改的代码。

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

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

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

    <Grid.RowDefinitions>
        <RowDefinition Height="75" />
        <RowDefinition Height="625" />
    </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>
    
  • 生成项目。

    创建数据绑定控件

    通过将 Product 表从“数据源”窗口拖到 WPF 设计器中,创建显示客户记录的控件。

  • 在“数据源”窗口中,单击“Product”节点的下拉菜单,然后选择“详细信息”

  • 展开“Product”节点

  • 在本示例中,某些字段不会显示,因此只需单击下列节点旁边的下拉菜单,然后选择“无”

  • ProductCategoryID

  • ProductModelID

  • ThumbnailPhotoFileName

  • rowguid

  • ModifiedDate

  • 单击“ThumbNailPhoto”节点旁边的下拉菜单,然后选择“图像”

    默认情况下,已将“数据源”窗口中表示图片的项的默认控件设置为“无”。 这是因为,图片是作为字节数组存储在数据库中的,并且从简单的字节数组到大型应用程序的可执行文件都可以包含在字节数组中。

  • 从“数据源”窗口,将“Product”节点拖到包含按钮的行下方的网格行

    Visual Studio 生成 XAML,它定义了一组绑定到“Products”表中的数据的控件。 它还会生成用于加载数据的代码。 有关生成的 XAML 和代码的详细信息,请参阅在 Visual Studio 中将 WPF 控件绑定到数据

  • 在设计器中,单击“Product ID”标签旁边的文本框

  • 在“属性”窗口,选中“IsReadOnly”属性旁边的复选框

    添加可让用户通过“”和“”按钮来浏览产品记录的代码<>

  • 在设计器中,双击窗口窗面上的“<”按钮。

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

  • 修改 Window_Loaded 事件处理程序,使 ProductViewSourceAdventureWorksLTDataSetAdventureWorksLTDataSetProductTableAdapter 位于该方法的外部,并使它们在整个窗体中可访问。 仅向窗体全局声明这些项,并在 Window_Loaded 事件处理程序内为这些项赋值,如下所示:

    private AdventureWorksProductsEditor.AdventureWorksLTDataSet AdventureWorksLTDataSet; private AdventureWorksProductsEditor.AdventureWorksLTDataSetTableAdapters.ProductTableAdapter adventureWorksLTDataSetProductTableAdapter; private System.Windows.Data.CollectionViewSource productViewSource; private void Window_Loaded(object sender, RoutedEventArgs e) AdventureWorksLTDataSet = ((AdventureWorksProductsEditor.AdventureWorksLTDataSet)(this.FindResource("adventureWorksLTDataSet"))); // Load data into the table Product. You can modify this code as needed. adventureWorksLTDataSetProductTableAdapter = new AdventureWorksProductsEditor.AdventureWorksLTDataSetTableAdapters.ProductTableAdapter(); adventureWorksLTDataSetProductTableAdapter.Fill(AdventureWorksLTDataSet.Product); productViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("productViewSource"))); productViewSource.View.MoveCurrentToFirst(); Dim ProductViewSource As System.Windows.Data.CollectionViewSource Dim AdventureWorksLTDataSet As AdventureWorksProductsEditor.AdventureWorksLTDataSet Dim AdventureWorksLTDataSetProductTableAdapter As AdventureWorksProductsEditor.AdventureWorksLTDataSetTableAdapters.ProductTableAdapter Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded AdventureWorksLTDataSet = CType(Me.FindResource("AdventureWorksLTDataSet"), AdventureWorksProductsEditor.AdventureWorksLTDataSet) 'Load data into the table Product. You can modify this code as needed. AdventureWorksLTDataSetProductTableAdapter = New AdventureWorksProductsEditor.AdventureWorksLTDataSetTableAdapters.ProductTableAdapter() AdventureWorksLTDataSetProductTableAdapter.Fill(AdventureWorksLTDataSet.Product) ProductViewSource = CType(Me.FindResource("ProductViewSource"), System.Windows.Data.CollectionViewSource) ProductViewSource.View.MoveCurrentToFirst() End Sub if (productViewSource.View.CurrentPosition > 0) productViewSource.View.MoveCurrentToPrevious(); If ProductViewSource.View.CurrentPosition > 0 Then ProductViewSource.View.MoveCurrentToPrevious() End If if (productViewSource.View.CurrentPosition < ((CollectionView)productViewSource.View).Count - 1) productViewSource.View.MoveCurrentToNext(); If ProductViewSource.View.CurrentPosition < CType(ProductViewSource.View, CollectionView).Count - 1 Then ProductViewSource.View.MoveCurrentToNext() End If

    这将生成并运行应用程序。 检查下列各项:

  • 文本框显示具有图片的第一条产品记录的数据。 此产品的产品 ID 为 713,名称为“Long-Sleeve Logo Jersey, S”

  • 可以单击 >< 按钮来导航其他产品记录。

  • 在某一产品记录中,更改“大小”值,然后依次“保存更改”

  • 关闭该应用程序,然后在 Visual Studio 中按 F5 重启该应用程序

  • 导航到已更改的产品记录,然后验证是否已保存更改。

  • 关闭该应用程序。

    完成本演练后,你可以尝试以下相关任务:

  • 了解如何使用 Visual Studio 中的“数据源”窗口将 WPF 控件绑定到其他类型的数据源上。 有关详细信息,请参阅将 WPF 控件绑定到 WCF 数据服务

  • 了解如何使用 Visual Studio 中的“数据源”窗口在 WPF 控件中显示相关数据(即父-子关系中的数据)。 有关详细信息,请参阅演练:在 WPF 应用中显示相关数据

  • 在 Visual Studio 中将 WPF 控件绑定到数据
  • Visual Studio 中的数据集工具
  • 数据绑定概述
  •