Accessing Business Data in WPF Applications

As more and more developers are looking to use Windows Presentation Foundation (WPF) as their technology for future user interfaces, there is also a growing need to know how to access business database data from WPF application.

That said, business applications often have windows or forms that allow users to add, edit, and delete data, corresponding to the four basic functions of SQL databases: create, read, update, and delete (CRUD). WPF includes very versatile support for data binding, and thus accessing database data using ADO.NET or LINQ is possible.

However, in Visual Studio 2008 the database data support for WPF applications is still lacking behind the database support in WinForms (Windows Forms) applications. For example, you cannot simply drag and drop a data source onto the form, and be able to see how Visual Studio automatically creates data access components and manipulation controls for you.

As you might imagine, WPF is still perfectly capable of accessing data from ADO.NET data sources; it just requires a little bit of more work (presently). You can start with the simplest possible WPF example: an application that is able to display data from an Access 2003 .mdb database file.

Introducing the Sample Application

The sample application to accompany this article can be seen in Figure 1. The application has a single window that mimics those seen in many organizations: It has the ability to browse data, make changes, and add and delete records.

Figure 1: The sample application as it looks like on Windows Vista.

In the sample application’s case, the data being edited is customer data. Editing is done through a simple list box control on the left, editing fields on the right, and Next and Previous buttons to help with browsing. Below those, you can find three more buttons: one to save changes, one to add a new customer record, and a third to delete one.

The database behind the application is a simple, one-table database. It contains a table called Customers, which in turn contains fields to store the contact details such as address, phone number, and so on. To allow an index number to be generated automatically, the first field of the table, named ID, is set to be an Access autonumber field. The table definition can be seen in Figure 2.

Figure 2: The structure of the sample table Customers.

Next, you will learn how to get started in displaying data in WPF programs.

Viewing Data on a Form

WPF applications support multiple ways to bind data into generic user interface controls. Data can be bound by using code, XAML, or in a combination of both. An example of a so-called XAML binding expression would be:

<TextBox Text="{Binding CustomerName}" />

Although there are multiple ways to get data on the screen, using a combination of binding expressions along with the form’s DataContext property is one of the simplest ways to achieve the goal. To display data on the screen, you would first add one or more basic controls (such text boxes as above), set the appropriate content property with a binding expression, and finally set the DataContext property for the entire window:

CustomersTableAdapter customersTableAdapter =
   new CustomersTableAdapter();
CustomersDataSet.CustomersDataTable customers =
   customersTableAdapter.GetData();
this.DataContext = customers;

After this, the application is able to display data from the database directly on the controls. However, the problem is that there is no way to browse the data, especially if all controls are just regular text boxes. To browse the data, you would need a couple of buttons on the form, and then write some C# code. For instance, if you want to add a “Next” button on the form, you could enable navigation to the next record (row) in the database with the following code:

private void nextButton_Click(
   object sender, RoutedEventArgs e)
{
   CollectionView view = (CollectionView)
      CollectionViewSource.
      GetDefaultView(this.DataContext);
   view.MoveCurrentToNext();
}

In WPF applications, you can use the CollectionView class to move back and forward in the database data records. For example, the MoveCurrentToNext and MoveCurrentToPrevious move the current record position forward and backward, respectively.

Of course, you need to be able to get to the CollectionView class first. To do so, you can use a class called CollectionViewSource from the System.Windows.Data namespace and its static GetDefaultView method. This method returns the currently used default view object as an ICollectionView interface. This is the reason you also need an explicit cast to get the CollectionView data type.

Oftentimes, business applications need lists of data. For example, you might want to allow the user to see a list of all customers, pick one, and then see more details. WPF applications do not (yet) have a built-in data grid control, but you could use a regular ListBox control to simulate one.

The ListBox control is a template control; this means that you can define a template for each row, and then have the control repeat that template for each data item associated with it. In this case, that data would of course be customer records.

Here is an example of a list box template used to display customer company name and the country on the same row:

<DataTemplate x_Key="CustomerListTemplate">
   <Grid ShowGridLines="False">
      <Grid.ColumnDefinitions>
         <ColumnDefinition Width="120" />
         <ColumnDefinition Width="50" />
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
         <RowDefinition Height="16" />
      </Grid.RowDefinitions>
      <TextBlock Text="{Binding CompanyName}"
         Grid.Column="0" Grid.Row="0" />
      <TextBlock Text="{Binding Country}"
         Grid.Column="1" Grid.Row="0" />
   </Grid>
</DataTemplate>

The DataTemplate XAML element starts the definition of a template named CustomerListTemplate. Inside each row, two TextBlocks are used to display the company name and the country. To display the information nicely formatted, a grid control can be used inside the listbox row. In addition to declaring the data template, the listbox control must be made aware of the template. This can be done with the following XAML code:

<ListBox ItemsSource="{Binding}"
   ItemTemplate="{StaticResource CustomerListTemplate}"
   Name="customerListBox" ... />

The next step is to connect the listbox to the current record. By default, the listbox only displays information from the database. Although merely displaying data can be useful in some cases, you would most often require more functionality.

The listbox control has a property named IsSynchronizedWithCurrentItem, which, when set to True, automatically makes the list follow the current record and also sets the current record if an item is clicked on the list. This is often exactly what is needed, so this property if indeed very useful.

More by Author

Must Read