Total votes: 1
Print: Print Article
Please login to rate or to leave a comment.
Published: 14 Mar 2008
Download Sample Code
Brian Mains explains how to perform data binding in WPF with LINQ.
WPF features a different data binding model than its predecessor. In WPF, it's possible to keep track of changes at both the source and destination level. To leverage this feature, certain requirements must be met for objects to take advantage of this change notification, all of which will be discussed in this article, all within the context of using LINQ and the LINQ to SQL designer.
WPF has a unique binding system, which can work in multiple directions. For instance, in an application, business objects are bound to the user interface. In the interface, changes made to values can automatically and immediately be saved in the business object. There are a variety of ways to bind data to the interface using the syntax below.
Binding mode works differently when binding element properties to other elements than with business objects. This article is going to focus on LINQ, and using LINQ to SQL to bind its auto-generated objects to a WPF interface. For example, the binding mode of
OneWayToSource does not update the interface when a change happens in the underlying business object. Rather, the interface is blank while the business object is updated. We'll get to this a bit later.
As you know, WPF provides a whole new group of base classes, controls, and events, along with a new approach to raise events and expose properties through dependencies. The first change that's important to know about is the addition of an
ObservableCollection class. This class implements the
INotifyCollectionChanged interface that WPF uses to automatically update the interface from changes to the collection it's bound to. Additions and deletions immediately reflect in the interface when bound to a class with this interface.
That will work for additions and deletions, but what about changes? For a business object being bound, there are certain requirements for automatic change notification. There are three approaches you can take:
- Implement dependency properties in your business object. Dependency properties are a new construct in WPF, and are out of scope for the article.
- Raise an event named
Name>Changed. This event must match the property name, and the class must raise the event.
- Implement the
INotifyPropertyChanged in the
System.ComponentModel namespace. This interface defines a
PropertyChanged event. The business object must fire this event every time any property value changes.
Binding with LINQ to SQL
LINQ to SQL is an object-relational mapper (ORM) tool that generates business objects that match your database structure. I wrote a separate article on this subject, which is available on this web site. There you can get more information about LINQ and the LINQ to SQL designer tool itself. When using LINQ to bind in a WPF interface, LINQ object already define the
INotifyPropertyChanged interface, which means change notification is possible for any values edited from another process.
Let's take a look at this in action. I've developed a simple screen that performs edits on the AdventureWorks database. I've developed some change notification capabilities to show when there are changes made to the underlying data context. The form below shows a list of products on the left sidebar. Selecting an item populates a partial form on the right, where some of the information is updated. Also on the far right is another listbox of reviews given for a particular product.
Let's start by selecting a product. In the form, I've included three buttons that alter values on the backend of the underlying business object.
Figure 1: A Test Form Being Updated
Clicking the first three buttons yield the result described above, which is pretty straightforward. Notice the size is not updated on the form. The form had these settings:
Listing 1: Form Binding Setup
Note that the code I used to perform one of the updates is below. I didn't want to update the bound object automatically, but went to the effort to retrieve the object through the data context, and change that object's properties (I needed the bound product's ID value though).
Listing 2: Value Altering Code
Notice that size is not updated on the interface, but when clicking the "View Backend Product Object Details", the following result shown below contains the updated size of 10:
Figure 2: Underlying Business Object Values
In retracing the steps a little bit: as I went through this test, as the first button fired updated the product object, the backend business object reflected this change. This change is verified by a count value shown below, that is written to the status label (through the click of another button). The following result shows that the change notification is immediately seen:
Figure 3: Change Notification Details
As I mentioned before, the form consists of two listboxes, one for products and one for reviews. The markup for the product listbox appears as:
Listing 3: Products ListBox
In the markup above, the products listbox has a data template that has a rounded border around a grid, which contains several object properties. It also defines styles to use whenever mousing over or out of the selected item, and what to show when the item is selected. To add a visual effect, I added an animation to change the color of the border when the mouse hovers over the item in the products list.
Note the property
IsSynchronizedWithCurrentItem for the listbox. Setting this property allows the current item in the underlying data source to be synonymous to the selected item in the listbox. This is helpful to use in a master details form layout, like we have here. The form itself uses a stackable panel that has the following setup:
Listing 4: Product Form
The details form binds to the products listbox, getting a reference to the selected item. The last listbox is bound manually, through the selection changed event on the products box. The element shows a list of reviews in a straightforward manner.
Listing 5: Reviews ListBox
As the items in the list are selected, the reviews are displayed in a linear fashion.
Collection Binding Challenges
When binding a collection to a list, WPF's change notification mechanism provides the ability to register updates to the
DataContext's business objects. However, additions and deletions of business objects do not fit within that mold. This is because the
EntitySet objects, collection-based objects in LINQ, do not implement the
INotifyCollectionChanged or inherit from the
ObservableCollection. It also isn't related to the
BindingList object that also supports change notifications. Therefore, the objects cannot notify the UI about changes that occur in the list. It may be possible to develop a wrapper around these classes and add these features; however, by default LINQ to SQL works in a specialized manner. I thought that I might be able to make use of the
GetNewBindingList method on the table or entity set, but that didn't work either.
LINQ is a hot new topic, and using LINQ to SQL, it's easy to develop a base architecture that supports change notification. This works well in some respects with WPF. You've seen above how LINQ objects and their change notification immediately reflect in the UI, depending on the binding mode. And you've seen how easy it is to setup an interface to work with this all. Check out the sample project attached to see it in action. It requires the AdventureWorks database installed on your machine. I have it installed on my local database server; change the connection string to point to your machine instead.
Brian Mains is an application developer consultant with Computer Aid Inc. He formerly worked with the Department of Public Welfare.
In both places of business, he developed both windows and web applications, small and large, using the latest .NET technologies. In addition, he had spent many hou...
This author has published 73 articles on DotNetSlackers. View other articles or the complete profile here.
You might also be interested in the following related blog posts
ASP.NET MVC Grid View - Data Binding To Large Database Using LINQ
RadScheduler for WinForms data binding and occurrence exceptions
Introducing Versatile DataSources
How to display data from different tables using one data source
Samedi.NET special Silverlight event in Montreal
Index for Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update
BulletedList in Silverlight
ASP.NET 4 Beta 2 - New Version, New Docs, New MSDN Site !
Announcing Microsoft Ajax Library (Preview 6) and the Microsoft Ajax Minifier
LINQ to SQL, Lazy Loading and Prefetching
Please login to rate or to leave a comment.