Practical .NET

Integrating with the .NET Framework UI Controls

With a little bit of code (along with a .NET interface and collection), you can integrate the properties on your classes with the .NET user interface controls to simplify your presentation layer.

The .NET Framework team obviously assumes you'll build your applications and the classes that make up your application a certain way. If you leverage those assumptions you'll get lots of cool benefits (and, if you don't leverage those benefits…well, you'll get to do a lot more work).

For instance, the user interface controls you can drag onto your WPF or Silverlight forms (TextBoxes, DropDownList, and so on) assume that you'll bind class properties to them. Those controls look for specific features in your classes; if you build those features into your code, you'll get a lot of functionality for free. The benefit is that you can build those objects independent of your UI, which supports automated testing, parallel development and loose coupling between application components.

One example of how you can integrate your classes with a XAML UI is the INotifyPropertyChanged interface. Adding this interface (and some code) to your classes gives you some almost magical benefits. For instance, if you have an object whose property is bound to and displayed in some user interface control, the control will automatically update in your user interface if you update the property from code. There's no need to do anything to make the user interface display the property's latest value: you don't need to update the control or call a Refresh method on the control (or the form).

Adding the INotifyPropertyChanged interface to your class is easy:

Public Class Product
    Implements ComponentModel.INotifyPropertyChanged

Visual Studio will then add the interface's one required member, an event called PropertyChanged:

Public Event PropertyChanged(sender As Object, 
  e As System.ComponentModel.PropertyChangedEventArgs) Implements _
        System.ComponentModel.INotifyPropertyChanged.PropertyChanged

The .NET UI controls look for this interface, and when they find it, automatically subscribe to any PropertyChanged methods you fire. In those events, you need only pass the name of the property being changed to cause the .NET user interface controls to pick up and display the latest value for the property. The typical place to put that is in the setter of the property being changed:

Private _Description As String
  Public Property Description As String
    Get
      Return _Description
    End Get
    Set(value As String)
      _Description = value
      RaiseEvent PropertyChanged(Me, 
         New ComponentModel.PropertyChangedEventArgs("Description"))
    End Set
  End Property

Rather than repeat the RaiseEvent code in every property, it makes sense to centralize it in a method of your own, like this:

Private Sub RaisePropertyChanged(PropertyName As String)
    RaiseEvent PropertyChanged(Me,
       New ComponentModel.PropertyChangedEventArgs(PropertyName))
  End Sub

With properties that are dependent on other properties, you may want to raise an event in other locations than the setter of a property. For instance, let's say you have a readonly ExtendedPrice property that's calculated from two other properties, Price and Quantity:

Public ReadOnly Property ExtendedPrice As Decimal
    Get
      Return Me.Price * Me.Quantity
    End Get
  End Property

In that case, changing either the Price or Quantity properties not only changes the property being updated, but also changes the ExtendedPrice property. To support that you'd want to raise the property changed event for all the affected properties in the setter of the properties that drive ExtendedPrice. The Quantity property would look like this:

Private _Quantity As Integer
  Public Property Quantity As Integer
    Get
      Return _Quantity
    End Get
    Set(value As Integer)
      _Quantity = value
      RaisePropertyChanged("Quantity")
      RaisePropertyChanged("ExtendedPrice")
    End Set
  End Property

Now, when you update the Quantity property (or any property that calls your RaisePropertyChanged method), any UI control tied to your Quantity or ExtendedPrice will automatically display the change. The only entanglement between your classes and the UI is when you set the data source on the UI control to an instance of your class.

However, sometimes you bind your controls to collections of objects—DataGridViews, for instance. In those scenarios, it's not enough to notify the UI control of changes in properties—you also want to notify the control about additions or deletions in the list of objects to which the control is bound. Here again, the .NET Framework provides a solution: The ObservableCollection generic collection class. As you create the objects that will be displayed, just pass the collection to the grid's ItemSource property:

Dim prods As New ObjectModel.ObservableCollection(Of Product)
  prods.Add(New Product("A123"))
  prods.Add(New Product("B456"))
  Me.DataGrid1.ItemsSource = prods

Now, if in your code you add or remove an item from the custs collection, your UI will update automatically. You could write code to make that happen yourself; but by leveraging the INotifyPropertyChanged interface and the ObservableCollection class, you get all of the benefits, and minimize the entanglements between your UI and your classes.

About the Author

Peter Vogel is a principal in PH&V Information Services, specializing in Web development with expertise in SOA, client-side development, and user interface design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His most recent book ("rtfm*") is on writing effective user manuals, and his blog on language and technical writing can be found at rtfmphvis.blogspot.com.

comments powered by Disqus

Reader Comments:

Wed, Jan 25, 2012 Philip

Yeah I agree with you Peter, its best to keep the bindings as simple as possible. The more you work with them the more intuitive it becomes to spot where the problems lie. Admittedly it can be confusing at times. The debugging features added to Silverlight 4 and 5 (not sure if they all exist in WPF) do make it easier though.

Tue, Jan 24, 2012 Peter Vogel Canada

Brian: Unfortunately I don't know much about WinForms in .NET--I'll see if I can swing back around to this later. HG/Philip: Back when I did work in Winforms (pre-.NET) databinding was awful--except in Microsoft Access. Microsoft has continually been improving its databinding solutions in .NET, reaching its current peak, I think, in Silverlight. The trick is, I think, is to use databinding without trying to "enhance" it too much. If you start getting clever and interfering with the process you can make your databound solution more complicated without adding any value.

Tue, Jan 24, 2012 Brian

I use INotifyPropertyChanged on my ViewModels using WinForms. I would appreciate any light you can shed on using ObservableCollections or equivalent methods for binding to common WinForm controls. Thanks!

Tue, Jan 24, 2012 HG NYC

Binding is a beauty to write and a pain to debug. Factor in the full dev cycle - with changes, and more changes, and templates swelling into multipage monsters, and the benefits of binding become less obvious.

Tue, Jan 24, 2012 Philip

Yeah I spose it stems from the way I was taught WPF from the start, that data binding is a core component. Its not that I dont think its special, data binding was a revelation for me (having not used it in Windows Forms), in fact I cant imagine WPF without it. I guess I assume that anyone who has even a basic understanding of WPF would also understand data binding. I cant imagine WPF without data binding! ;)

Tue, Jan 24, 2012 Peter Vogel Canada

Philip: You may be suffering from the "well-if-I-know-it-then-how-important-can-it-be" syndrome (closely related to the "if-I-can-do-it-it's-not-really-special" syndrome). I'm constantly surprised at the number of people who find this new (hence, this column). But it's also not just a WPF thing: this works everywhere.

Mon, Jan 23, 2012 Philip

Hmm...I figured this was obligatory WPF (and Silverlight) usage knowledge. If you're not using WPF this way you might as well still be using Windows Forms (in my humble opinion). But a good knowledge share article none-the-less.

Add Your Comments Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.