指南:在混合应用程序中绑定数据

将数据源绑定到控件对于向用户提供对基础数据的访问权限至关重要,无论是使用 Windows 窗体还是 WPF。 本演练演示如何在包含 Windows 窗体和 WPF 控件的混合应用程序中使用数据绑定。

本演练涉及以下任务:

  • 创建项目。

  • 定义数据模板。

  • 指定表单布局。

  • 指定数据绑定。

  • 使用互操作显示数据。

  • 将数据源添加到项目。

  • 绑定到数据源。

有关本演练中演示的任务的完整代码列表,请参阅 混合应用程序示例中的数据绑定

完成后,你将了解混合应用程序中的数据绑定功能。

先决条件

需要以下组件才能完成本演练:

  • Visual Studio。

  • 访问 Microsoft SQL Server 上运行的 Northwind 示例数据库。

创建项目

创建和设置项目

  1. 创建名为 WPFWithWFAndDatabinding的 WPF 应用程序项目。

  2. 在解决方案资源管理器中,添加对以下程序集的引用。

    • WindowsFormsIntegration

    • System.Windows.Forms

  3. 在 WPF 设计器中打开 MainWindow.xaml。

  4. Window 元素中,添加以下 Windows 窗体命名空间映射。

    xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
    
  5. 通过分配Name属性来命名默认Grid元素mainGrid

    <Grid x:Name="mainGrid">
    

定义数据模板

客户的主列表显示在控件 ListBox 中。 下面的代码示例定义一个 DataTemplate 对象,该对象用于控制 ListBox 控件的可视化树 ListItemsTemplate。 这个 DataTemplate 被分配给 ListBox 控件的 ItemTemplate 属性。

定义数据模板

  • 将以下 XAML 复制到Grid元素的声明部分中。

    <Grid.Resources>
        <DataTemplate x:Key="ListItemsTemplate">
            <TextBlock Text="{Binding Path=ContactName}"/>
        </DataTemplate>
    </Grid.Resources>
    

指定窗体布局

窗体的布局由包含三行和三列的网格定义。 Label 提供控件以标识 Customers 表中的每一列。

设置网格布局

  • 将以下 XAML 代码复制到 Grid 元素声明中。

    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    

设置标签控件

  • 将以下 XAML 代码复制到 Grid 元素的声明中。

    <StackPanel Orientation="Vertical" Grid.Row="0" Grid.Column="1">
        <Label Margin="20,38,5,2">First Name:</Label>
        <Label Margin="20,0,5,2">Company Name:</Label>
        <Label Margin="20,0,5,2">Phone:</Label>
        <Label Margin="20,0,5,2">Address:</Label>
        <Label Margin="20,0,5,2">City:</Label>
        <Label Margin="20,0,5,2">Region:</Label>
        <Label Margin="20,0,5,2">Postal Code:</Label>
    </StackPanel>
    

指定数据绑定

客户的主列表显示在控件 ListBox 中。 附加的ListItemsTemplateTextBlock控件绑定到数据库中的ContactName字段。

每个客户记录的详细信息显示在多个 TextBox 控件中。

指定数据绑定

  • 将以下 XAML 复制到 Grid 元素的声明中。

    Binding 类将 TextBox 控件绑定到数据库中的相应字段。

    <StackPanel Orientation="Vertical" Grid.Row="0" Grid.Column="0">
        <Label Margin="20,5,5,0">List of Customers:</Label>
        <ListBox x:Name="listBox1" Height="200" Width="200" HorizontalAlignment="Left" 
           ItemTemplate="{StaticResource ListItemsTemplate}" IsSynchronizedWithCurrentItem="True" Margin="20,5,5,5"/>
    </StackPanel>
    
    <StackPanel Orientation="Vertical" Grid.Row="0" Grid.Column="2">
        <TextBox Margin="5,38,5,2" Width="200" Text="{Binding Path=ContactName}"/>
        <TextBox Margin="5,0,5,2" Width="200" Text="{Binding Path=CompanyName}"/>
        <TextBox Margin="5,0,5,2" Width="200" Text="{Binding Path=Phone}"/>
        <TextBox Margin="5,0,5,2" Width="200" Text="{Binding Path=Address}"/>
        <TextBox Margin="5,0,5,2" Width="200" Text="{Binding Path=City}"/>
        <TextBox Margin="5,0,5,2" Width="30" HorizontalAlignment="Left" Text="{Binding Path=Region}"/>
        <TextBox Margin="5,0,5,2" Width="50" HorizontalAlignment="Left" Text="{Binding Path=PostalCode}"/>
    </StackPanel>
    

使用互操作来显示数据

与所选客户对应的订单显示在名为dataGridView1System.Windows.Forms.DataGridView的控件中。 该 dataGridView1 控件绑定到后台代码文件中的数据源。 控件 WindowsFormsHost 是此 Windows 窗体控件的父级。

在 DataGridView 控件中显示数据

  • 将以下 XAML 复制到Grid元素的声明中。

    <WindowsFormsHost Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Margin="20,5,5,5" Height="300">
        <wf:DataGridView x:Name="dataGridView1"/>
    </WindowsFormsHost>
    

将数据源添加到项目

使用 Visual Studio,可以轻松地将数据源添加到项目中。 此过程向项目添加强类型数据集。 还会添加几个其他支持类,例如为每个所选表添加表适配器。

添加数据源

  1. “数据 ”菜单中,选择“ 添加新数据源”。

  2. 数据源配置向导中,使用数据集创建与 Northwind 数据库的连接。 有关详细信息,请参阅 “如何:连接到数据库中的数据”。

  3. 数据源配置向导提示时,请将连接字符串另存为 NorthwindConnectionString

    重要

    在连接字符串中存储敏感信息(如密码)可能会影响应用程序的安全性。 使用 Windows 身份验证(也称为集成安全性)是控制对数据库的访问的更安全方法。 有关详细信息,请参阅保护连接信息

  4. 当系统提示你选择数据库对象时,请选择 CustomersOrders 表,并命名生成的数据集 NorthwindDataSet

绑定到数据源

System.Windows.Forms.BindingSource 组件为应用程序的数据源提供统一接口。 绑定到数据源是在后台代码文件中实现的。

绑定到数据源

  1. 打开名为 MainWindow.xaml.vb 或 MainWindow.xaml.cs 的代码后台文件。

  2. 将以下代码复制到 MainWindow 类定义中。

    此代码声明 BindingSource 连接到数据库的组件和关联的帮助程序类。

    private System.Windows.Forms.BindingSource nwBindingSource;
    private NorthwindDataSet nwDataSet;
    private NorthwindDataSetTableAdapters.CustomersTableAdapter customersTableAdapter =
        new NorthwindDataSetTableAdapters.CustomersTableAdapter();
    private NorthwindDataSetTableAdapters.OrdersTableAdapter ordersTableAdapter =
        new NorthwindDataSetTableAdapters.OrdersTableAdapter();
    
    Private nwBindingSource As System.Windows.Forms.BindingSource
    Private nwDataSet As NorthwindDataSet
    Private customersTableAdapter As New NorthwindDataSetTableAdapters.CustomersTableAdapter()
    Private ordersTableAdapter As New NorthwindDataSetTableAdapters.OrdersTableAdapter()
    
  3. 将以下代码复制到构造函数中。

    此代码创建并初始化 BindingSource 组件。

    public MainWindow()
    {
        InitializeComponent();
    
        // Create a DataSet for the Customers data.
        this.nwDataSet = new NorthwindDataSet();
        this.nwDataSet.DataSetName = "nwDataSet";
    
        // Create a BindingSource for the Customers data.
        this.nwBindingSource = new System.Windows.Forms.BindingSource();
        this.nwBindingSource.DataMember = "Customers";
        this.nwBindingSource.DataSource = this.nwDataSet;
    }
    
    Public Sub New()
        InitializeComponent()
    
        ' Create a DataSet for the Customers data.
        Me.nwDataSet = New NorthwindDataSet()
        Me.nwDataSet.DataSetName = "nwDataSet"
    
        ' Create a BindingSource for the Customers data.
        Me.nwBindingSource = New System.Windows.Forms.BindingSource()
        Me.nwBindingSource.DataMember = "Customers"
        Me.nwBindingSource.DataSource = Me.nwDataSet
    
    End Sub
    
  4. 打开 MainWindow.xaml。

  5. 在“设计”视图或 XAML 视图中,选择该 Window 元素。

  6. 在“属性”窗口中,单击“ 事件 ”选项卡。

  7. 双击 Loaded 事件。

  8. 将以下代码复制到 Loaded 事件处理程序中。

    此代码将 BindingSource 组件分配为数据上下文并填充 CustomersOrders 适配器对象。

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        // Fill the Customers table adapter with data.
        this.customersTableAdapter.ClearBeforeFill = true;
        this.customersTableAdapter.Fill(this.nwDataSet.Customers);
    
        // Fill the Orders table adapter with data.
        this.ordersTableAdapter.Fill(this.nwDataSet.Orders);
    
        // Assign the BindingSource to
        // the data context of the main grid.
        this.mainGrid.DataContext = this.nwBindingSource;
    
        // Assign the BindingSource to
        // the data source of the list box.
        this.listBox1.ItemsSource = this.nwBindingSource;
    
        // Because this is a master/details form, the DataGridView
        // requires the foreign key relating the tables.
        this.dataGridView1.DataSource = this.nwBindingSource;
        this.dataGridView1.DataMember = "FK_Orders_Customers";
    
        // Handle the currency management aspect of the data models.
        // Attach an event handler to detect when the current item
        // changes via the WPF ListBox. This event handler synchronizes
        // the list collection with the BindingSource.
        //
    
        BindingListCollectionView cv = CollectionViewSource.GetDefaultView(
            this.nwBindingSource) as BindingListCollectionView;
    
        cv.CurrentChanged += new EventHandler(WPF_CurrentChanged);
    }
    
    Private Sub Window_Loaded( _
    ByVal sender As Object, _
    ByVal e As RoutedEventArgs)
    
        ' Fill the Customers table adapter with data.
        Me.customersTableAdapter.ClearBeforeFill = True
        Me.customersTableAdapter.Fill(Me.nwDataSet.Customers)
    
        ' Fill the Orders table adapter with data.
        Me.ordersTableAdapter.Fill(Me.nwDataSet.Orders)
    
        ' Assign the BindingSource to 
        ' the data context of the main grid.
        Me.mainGrid.DataContext = Me.nwBindingSource
    
        ' Assign the BindingSource to 
        ' the data source of the list box.
        Me.listBox1.ItemsSource = Me.nwBindingSource
    
        ' Because this is a master/details form, the DataGridView
        ' requires the foreign key relating the tables.
        Me.dataGridView1.DataSource = Me.nwBindingSource
        Me.dataGridView1.DataMember = "FK_Orders_Customers"
    
        ' Handle the currency management aspect of the data models.
        ' Attach an event handler to detect when the current item 
        ' changes via the WPF ListBox. This event handler synchronizes
        ' the list collection with the BindingSource.
        '
    
        Dim cv As BindingListCollectionView = _
            CollectionViewSource.GetDefaultView(Me.nwBindingSource)
    
        AddHandler cv.CurrentChanged, AddressOf WPF_CurrentChanged
    
    End Sub
    
  9. 将以下代码复制到 MainWindow 类定义中。

    此方法处理 CurrentChanged 事件并更新数据绑定的当前项。

    // This event handler updates the current item
    // of the data binding.
    void WPF_CurrentChanged(object sender, EventArgs e)
    {
        BindingListCollectionView cv = sender as BindingListCollectionView;
        this.nwBindingSource.Position = cv.CurrentPosition;
    }
    
    ' This event handler updates the current item 
    ' of the data binding.
    Private Sub WPF_CurrentChanged(ByVal sender As Object, ByVal e As EventArgs)
        Dim cv As BindingListCollectionView = sender
        Me.nwBindingSource.Position = cv.CurrentPosition
    End Sub
    
  10. 按 F5 生成并运行应用程序。

另请参阅