Walkthrough: Binding to Data in Hybrid Applications
Binding a data source to a control is essential for providing users with access to underlying data, whether you're using Windows Forms or WPF. This walkthrough shows how you can use data binding in hybrid applications that include both Windows Forms and WPF controls.
Tasks illustrated in this walkthrough include:
Creating the project.
Defining the data template.
Specifying the form layout.
Specifying data bindings.
Displaying data by using interoperation.
Adding the data source to the project.
Binding to the data source.
For a complete code listing of the tasks illustrated in this walkthrough, see Data Binding in Hybrid Applications Sample.
When you are finished, you will have an understanding of data binding features in hybrid applications.
Note: |
---|
The dialog boxes and menu commands you see might differ from those described in Help, depending on your active settings or edition. To change your settings, choose Import and Export Settings on the Tools menu. |
Prerequisites
To complete this walkthrough, you will need:
Access to the Northwind sample database running on Microsoft SQL Server.
Development Tools for .NET Framework 3.0, which enable you to create a WPF application project. For information on installing these tools, see Installation Instructions for the Windows SDK.
Creating the Project
To create and set up the project
Create a Windows Application (WPF) project named WPFWithWFAndDatabinding.
In Solution Explorer, add a reference to the WindowsFormsIntegration assembly, which is named WindowsFormsIntegration.dll.
The default location for this file is %programfiles%\Reference Assemblies\Microsoft\Framework\v3.0\WindowsFormsIntegration.dll.
In Solution Explorer, add a reference to the Windows Forms assembly, which is named System.Windows.Forms.dll.
In the Windows Forms Designer, open Window1.xaml.
At the start of the file, map the Windows Forms namespaces with the following code.
<Window x:Class="WPFWithWFAndDatabinding.Window1" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" Title="WPFWithWFAndDatabinding" Loaded="WindowLoaded" >
<Window x:Class="Window1" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" Title="WPFWithWFAndDatabinding" Loaded="WindowLoaded" >
Name the default Grid element
mainGrid
by assigning the Name property.<Grid x:Name="mainGrid">
<Grid x:Name="mainGrid">
Defining the Data Template
The master list of customers is displayed in a ListBox control. The following code example defines a DataTemplate object named ListItemsTemplate
that controls the visual tree of the ListBox control. This DataTemplate is assigned to the ListBox control's ItemTemplate property.
To define the data template
Copy the following code into the Grid element's declaration.
<Grid.Resources> <DataTemplate x:Key="ListItemsTemplate"> <TextBlock Text="{Binding Path=ContactName}"/> </DataTemplate> </Grid.Resources>
<Grid.Resources> <DataTemplate x:Key="ListItemsTemplate"> <TextBlock Text="{Binding Path=ContactName}"/> </DataTemplate> </Grid.Resources>
Specifying the Form Layout
The layout of the form is defined by a grid with three rows and three columns. Label controls are provided to identify each column in the Customers table.
To set up the Grid layout
Copy the following code into the Grid element's declaration.
<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>
<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>
To set up the Label controls
Copy the following code into the Grid element's declaration.
<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>
<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>
Specifying Data Bindings
The master list of customers is displayed in a ListBox control. The attached ListItemsTemplate
binds a TextBlock control to the ContactName
field from the database.
The details of each customer record are displayed in several TextBox controls.
To specify data bindings
Copy the following code into the Grid element's declaration.
The Binding class binds the TextBox controls to the appropriate fields in the database.
<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>
<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>
Displaying Data by Using Interoperation
The orders corresponding to the selected customer are displayed in a System.Windows.Forms.DataGridView control named dataGridView1
. The dataGridView1
control is bound to the data source in the code-behind file. A WindowsFormsHost control is the parent of this Windows Forms control.
To display data in the DataGridView control
Copy the following code into the Grid element's declaration.
<WindowsFormsHost Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Margin="20,5,5,5" Height="300"> <wf:DataGridView x:Name="dataGridView1"/> </WindowsFormsHost>
<WindowsFormsHost Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Margin="20,5,5,5" Height="300"> <wf:DataGridView x:Name="dataGridView1"/> </WindowsFormsHost>
Adding the Data Source to the Project
With Microsoft Visual Studio 2005, you can easily add a data source to your project. This procedure adds a strongly typed data set to your project. Several other support classes, such as table adapters for each of the chosen tables, are also added.
To add the data source
Open Server Explorer and right-click on Data Connections.
From the context menu, select Add Connection… to create a connection to the Northwind database.
When you are prompted by the Data Source Configuration Wizard, save the connection string as NorthwindConnectionString.
Select the Customers and Orders tables, and name the generated data set NorthwindDataSet.
Binding to the Data Source
The System.Windows.Forms.BindingSource component provides a uniform interface for the application's data source. Binding to the data source is implemented in the code-behind file.
To bind to the data source
Open the code-behind file, which is named Window1.xaml.cs or Window1.xaml.vb.
Copy the following code into the
Window1
class definition.This code declares the BindingSource component and associated helper classes that connect to the database.
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()
Copy the following code into the
Window1
constructor, immediately following the call to theInitializeComponent
method.This code creates and initializes the BindingSource component.
public Window1() { 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
Copy the following code into the
Window1
class definition, following the constructor.This code defines the Loaded event handler, which assigns the BindingSource component as the data context and populates the
Customers
andOrders
adapter objects.private void WindowLoaded(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. // // NOTE: This is a workaround for a known issue in WPF Beta 2. // This step will not be necessary in later versions of WPF. BindingListCollectionView cv = CollectionViewSource.GetDefaultView( this.nwBindingSource) as BindingListCollectionView; cv.CurrentChanged += new EventHandler(WPF_CurrentChanged); }
Private Sub WindowLoaded( _ 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. ' ' NOTE: This is a workaround for a known issue in WPF Beta 2. ' This step will not be necessary in later versions of WPF. Dim cv As BindingListCollectionView = _ CollectionViewSource.GetDefaultView(Me.nwBindingSource) AddHandler cv.CurrentChanged, AddressOf WPF_CurrentChanged End Sub
Copy the following code into the
Window1
class definition, following theWindowLoaded
method.This method handles the CurrentChanged event and updates the current item of the data binding.
// 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. Sub WPF_CurrentChanged(ByVal sender As Object, ByVal e As EventArgs) Dim cv As BindingListCollectionView = sender Me.nwBindingSource.Position = cv.CurrentPosition End Sub
Press F5 to build and run the application.
See Also
Reference
Concepts
Walkthrough: Hosting a Windows Forms Composite Control in Windows Presentation Foundation
Walkthrough: Hosting a Windows Presentation Foundation Control in Windows Forms
Other Resources
Data Binding in Hybrid Applications Sample
Migration and Interoperability How-to Topics