Preface And Thanks
I am a .NET programmer, but a busy one, I do VB .NET and C#, ASP .NET / Winforms / WPF / WCF Flash Silverlight the lot. Basically I keep my toe in. But when I started writing this article series I naturally chose my favourite language (which happens to be C#). I since got an email from an individual who requested that I publish this series with source code in VB .NET and C#. I simply stated I didn't have time. So this individual (Robert Ranck) volunteered to help out, and do the translation to VB .NET, based on my orginal C# projects
So for that and the subsequent VB .NET projects that you will find here I ask you to thank Robert Ranck. Cheers Robert, your contributions will surely make this series more open to all .NET developers.
And another thanks also goes outKarl Shifflett (AKA the blog/article machine, also known as the Molenator) for answering my dumb VB .NET questions. And I'd also like to mention that Karl has just started a more advanced series of WPF articles (which at present will be in VB.NET, but will hopefully appear in C# as well). Karls new series will be excellent and I urge you all to encourage Karl on this series. Its not easy obligating ones self to write an entire series in one language let alone 2. Karls 1st article is locatedright here, have a look for yourself. Personally I love it.
Introduction
This article is the 5th in my series of beginners articles for WPF. In this article we will discuss databinding. The proposed schedule for this series will still be roughly as follows:
LayoutXAML vs Code / Markup Extensions And ResourcesCommands And EventsDependency Properties (previous article) DataBinding (this article)Styles/Templates
In this article I'm aiming to cover, is a brief introduction into the following:
The general idea behind databindingDataContextBasic databinding conceptsDatabinding syntaxDatabinding to UI elementsDatabinding to xmlDatabinding to collectionsDatabinding value convertorsDatabinding validation
I will NOT be covering the following collection based binding areas, so if you want to know more about these you'll have to do a bit of extra research using the links provided (see i'm 1/2 ok, at least I researched the correct links for you)
SortingFilteringGroupingRecord ManipulationMaster/Detail
Databinding is actually not that new (ok how its done in WPF is new) but we have has binding in ASP .NET and Winforms for some time now. WPF has borrowed from both of these to create a really really good binding framework. But what is this binding stuff, for those of you that have never heard of it.
Well basically binding allows UI Elements to obtain their data either from other UI Elements or business logic objects/classes. So in theory its very simply, we have a source that provides a value, and we have a target that wants to use the sources value, and we kind of glue them together using binding.
A typical binding arrangement is as follows:
Typically, each binding has these four components: a binding target object, a target property, a binding source, and a path to the value in the binding source to use.
The target property must be aDepenedency Property (which I've just covered). Most UIElement properties are dependency properties and most dependency properties, except read-only ones, support data binding by default.
That's a very simplified version of whats going on in binding.
Of course to facilitate these binding operations there are many seperate considerations and bits of syntax that need to be considered. In the next sub sections you will look at some (no not all, i'd be here all year) of the binding syntax and ideas/approaches to creating happy bindings.
There is one important thing to know before we get into the ins and outs of Databinding, and that is the DataContext property, that every FrameworkElement has. DataContext is a concept that allows elements to inherit information from their parent elements about the data source that is used for binding, as well as other characteristics of the binding, such as the path. DataContext can be set directly to a common language runtime (CLR) object, with the bindings evaluating to properties of that object. Alternatively, you can set the data context to a DataSourceProvider object.
This dependency property inherits property values. If there are child elements without other values for DataContext established through local values or styles, then the property system will set the value to be the DataContext value of the nearest parent element with this value assigned.
In XAML, DataContext is most typically set to as a Binding declaration. You can use either property element syntax or attribute syntax. And is normal set something like this
............
You can also use code to set DataContext, simply by using a .DataContext = Another thing to note is that if some object that inherits from a parents DataContext ommits which fields it will use to bind to, such as This means that the entire object that is used as its parents DataContext will be used to assign to the Tag property Before we can proceed onto looking at the nitty griity of databinding there are several key areas which we need to cover first. Namely Direction of the data flow What triggers source updates So we'll just spend a little bit of time on these 2 subjectsDirection Of The Data Flow As shown above in thethe general idea behind databinding section, flow of binding could be 2 way. There are several possibilities that can be configured when using databinding. These are controlled using theBinding.Mode values: OneWay binding causes changes to the source property to automatically update the target property, but changes to the target property are not propagated back to the source property. This type of binding is appropriate if the control being bound is implicitly read-only. TwoWay binding causes changes to either the source property or the target property to automatically update the other. This type of binding is appropriate for editable forms or other fully-interactive UI scenarios. OneTime causes the source property to initialize the target property, but subsequent changes do not propagate. This means that if the data context undergoes a change or the object in the data context changes, then the change is reflected in the target property. This type of binding is appropriate if you are using data where either a snapshot of the current state is appropriate to use or the data is truly static. OneWayToSource is the reverse of OneWay binding; it updates the source property when the target property changess. Default causes the default Mode value of target property to be used Use theBinding.Mode property to specify the direction of the data flow. To detect source changes in one-way or two-way bindings, the source must implement a suitable property change notification mechanism such asINotifyPropertyChanged. For an example, see How to: Implement Property Change Notification. Change notification is such an important lesson to learn in databinding that we need to look at that right now. So lets have a look at an example of using this interfaceINotifyPropertyChanged. To support OneWay or TwoWay binding to enable your binding target properties to automatically reflect the dynamic changes of the binding source, your class needs to provide the proper property changed notifications, this is whereINotifyPropertyChanged is used. using System.ComponentModel;namespace SDKSample{// This class implements INotifyPropertyChanged// to support one-way and two-way bindings// (such that the UI element updates when the source// has been changed dynamically)public class Person : INotifyPropertyChanged{private string name;// Declare the eventpublic event PropertyChangedEventHandler PropertyChanged;public Person(){}public Person(string value){this.name = value;}public string PersonName{get { return name; }set{name = value;// Call OnPropertyChanged whenever the property is updatedOnPropertyChanged("PersonName");}}// Create the OnPropertyChanged method to raise the eventprotected void OnPropertyChanged(string name){PropertyChangedEventHandler handler = PropertyChanged;if (handler != null){handler(this, new PropertyChangedEventArgs(name));}}}} And heres a VB .NET version Imports System.ComponentModel' This class implements INotifyPropertyChanged' to support one-way and two-way bindings' (such that the UI element updates when the source' has been changed dynamically)Public Class PersonImplements INotifyPropertyChangedPrivate personName As StringSub New()End SubSub New(ByVal Name As String)Me.personName = NameEnd Sub' Declare the eventPublic Event PropertyChanged As PropertyChangedEventHandlerImplements INotifyPropertyChanged.PropertyChangedPublic Property Name() As StringGetReturn personNameEnd GetSet(ByVal value As String)personName = value' Call OnPropertyChanged whenever the property is updatedOnPropertyChanged("Name")End SetEnd Property' Create the OnPropertyChanged method to raise the eventProtected Sub OnPropertyChanged(ByVal name As String)RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))End SubEnd Class To implementINotifyPropertyChanged you need to declare the PropertyChanged event and create the OnPropertyChanged method. Then for each property you want change notifications for, you call OnPropertyChanged whenever the property is updated. I can not tell you how important theINotifyPropertyChanged interface is, but believe me its very very important, and if you plan to use Binding in WPF, just get used to using theINotifyPropertyChanged interface. What Triggers Source Updates Bindings that are TwoWay or OneWayToSource listen for changes in the target property and propagate them back to the source. This is known as updating the source. For example, you may edit the text of a TextBox to change the underlying source value. As described in the last section, the direction of the data flow is determined by the value of theBinding.Mode property of the binding. However, does your source value get updated while you are editing the text or after you finish editing the text and point your mouse away from the TextBox? TheBinding.UpdateSourceTrigger property of the binding determines what triggers the update of the source. The options available are as follows : The following table provides an example scenario for eachBinding.UpdateSourceTrigger value using the TextBox as an example: UpdateSourceTrigger value When the Source Value Gets Updated LostFocus (default for TextBox.Text) When the TextBox control loses focus PropertyChanged As you type into the TextBox Explicit When the application calls UpdateSource There are many properties that may be used within theBinding class, as such I will not have time to cover all of them, though I shall attempt to go through the most common buts of syntax. As most binding will usually be set in XAML I will be concentrating on the XAML syntax, though it should be noted that anything that can be done in XAML can also be done in C#/VB .NET code behind. Ok so lets have a look at the basic syntax (we will cover more advanced stuff in the sections below). The most basic form of binding if to create a binding that binds to a value of an existing element (this is covered in more detail below also) I just wanted to introduce the syntax and go back and show you how to do theBinding.Mode andBinding.UpdateSourceTrigger stuff first. So here is probably one of the simplist Bindings that you will see. This example has 2 buttons, the 1st button (btnSource) has a Yellow Background property. The 2nd button uses the 1st button (btnSource), as the source for a Binding where the 1st button (btnSource) Background value is being used to set the 2nd buttons Background.Yellow BUtton I am bound to be Yellow Background So that'd fairly simple right. But I just wanted to go back and have a quick look at how we could also use theBinding.Mode andBinding.UpdateSourceTrigger properties within the binding sytnax. Well as it turns out, its fairly easy, we just add the extra property and its desired value into the binding expression such as An Important Note : Recall frompart 2 that I mentioned that Binding was a markupMarkupExtension. As such the XAML parser knows how to treat the { } sections. But really this is just shorthand, that can (if you prefer) be expressed using the longer more verbose syntax as shown below. This is a decision you will have to make yourself, me personally I prefer the { } syntax, though you dont get any intellisense help within Visual Studio if you do use the {} syntax. When you set out to set up a Binding there are several different things you need to consider What property do I want to bind to What property should we bind from Does it need to be OneWay or TwoWay etc etc Binding. If it needs to be a TwoWay/OneWayToSource Binding, was the source property a Dependency Property. It has to be to carry out TwoWay/OneWayToSource Binding Once you know or have considered all this, its really as easy as ABC. As part of the demo solution, you will find a project entitled "BindingToUIElements" which when run, will look like the following: This simple demo application shows 3 different bindings going on. Ill briefly discuss each of these now. 1. Simply Element Binding (Default Mode) This simple example uses the 1st buttons Background as the source value for the other 2 Buttons Background The code for which is as follows: 2. More Elaborate Binding (Default Mode) This simple example uses the SelectedItem.Content of a ComboBox as the source for a Binding. Where the Background of a Button is changed dependant on the SelectedItem.Content of the ComboBox The code for which is as follows:Green Blue Red 3. TwoWay Binding using UpdateSourceTrigger This simple example uses 2 TextBoxs, where there is a TwoWay Binding.Mode applied and the as the Binding.UpdateSourceTrigger is set to PropertyChanged, which means that the source of the Binding will be updated when the 2nd TextBoxs value changes The code for which is as follows: XML is used a lot these days, both for configuration information and data exchange, and indeed these days even for UI design. Remember XAML is a XML derivative. But that's not all we can use XML data for. We can infact bind to XML data. This is fairly easy to do in XAML, we can either have the XAML hold the XML data (though this is probably not the norm) or use external XML files. Either way the normal proceeding is to use a XmlDataProvider within the XAML/code. Like I said earlier as I thinking most Bindings will be done in XAML, ill stick to that. As part of the demo solution, you will find a project entitled "BindingToXML" which when run, will look like the following: The top 2 sections of this demo app using XAML held XML data, and the bottom 2 use an external XML file. XmlDataProvider Using XAML Held Data (inline XML data) It is entirely possible to hold all the XML data within the XAML file, and use this data as a source for Binding. Lets see an example of thisSam Raimi Evil Dead II Jonathan Demme Silence Of The Lambs Ridley Scott Alien It can be seen from this example, that we use an in line (in the XAML) xml dataset, for the XmlDataProvider. And that we use the XmlDataProvider as the BindingSource for the ListBox. In this example the 1st ListBox shows all Films/Titles as we are just fetching the Film/Title nodeset using the Binding.XPath=Film/Title so we get all Titles shows. The 2nd ListBox is a bit fussier and uses a bit of XPath notation to traverse the attribute axis and ony fetch those nodes that have Year > 1991, so we get less nodes returned XmlDataProvider Using External XML File As I say though its going to be more common to use external XML files with the XmlDataProvider, which can be done as follows. Where the XmlDataProvider Source property is set to the external XML file. Using this arrangement is much the same as we saw before where we can use XPath to fetch all the nodes or use XPath to only match those nodes where the attribute match the requirements. In this example the 2nd ListBox only shows "Mexican" resteraunts from the XML file, using the following XPath And heres the full example And heres the associated XML file (should you be curious about its structure)The MeatHouse 01237 78516 yada@here.com VegHead 99999 mmm-vegies@here.com Mexican't (El Mariachi) 464654654 mex@here.com NOTE : Using XML to provide Binding values, is fine, but dont expect that you will be able to update XML simply by using a Binding.Mode set to TwoWay. That wont work. XML data binding is a simple one way/not updatable type of arrangement. Binding To XLINQ Although I'm not going to go into this, Beatriz The Binding Queen Costa has a good blog entry righthere if you are curious Typically WPF development will more than likely involve binding to an entire collection at some point. Now this is very very easy to do in WPF. As with most things there is many ways to do this, i'll outline 2 possible way, but of course there will be more. I just like these ways thats all. One important thing to ALWAYS keep in mind is change notification, recall we addressed that for individual classes by using theINotifyPropertyChanged interface. But what about Collections that will hold objects, what should we do about that? Well as luck would have it, these days there is a nice ObserverableCollection that fills this spot quite nicely. This collection takes care of notifying the UI everytime an element in the collection is added/removed. We still need to make sure that each of the held objects does its own change notification using theINotifyPropertyChanged interface. But by using ObserverableCollection and classes that implementINotifyPropertyChanged we are sitting pretty, no change will pass us by. As part of the demo solution, you will find a project entitled "BindingToCollections" which when run, will look like the following: So binding to such a collection becomes a snap. Heres 2 possible ways to do this with using ListBoxes. Binding To Collections In Code Behind The 1st ListBox has its ItemSource set in code behind as follows: using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;using System.Collections.ObjectModel;namespace BindingToCollections{/// /// Interaction logic for Window1.xaml/// public partial class Window1 : Window{private People people = new People();public Window1(){InitializeComponent();people.Add(new Person { PersonName = "Judge Mental" });people.Add(new Person { PersonName = "Office Rocker" });people.Add(new Person { PersonName = "Sir Real" });this.lstBox1.ItemsSource = people;}}} And in VB .NET Imports SystemImports System.Collections.GenericImports System.LinqImports System.TextImports System.WindowsImports System.Windows.ControlsImports System.Windows.DataImports System.Windows.DocumentsImports System.Windows.InputImports System.Windows.MediaImports System.Windows.Media.ImagingImports System.Windows.NavigationImports System.Windows.ShapesImports System.Collections.ObjectModel''' ''' Interaction logic for Window1.xaml ''' Partial Public Class Window1Inherits WindowPrivate people As New People()Public Sub New()InitializeComponent()Dim _Person As New Person_Person.PersonName = "Judge Mental"people.Add(_Person)_Person.PersonName = "Office Rocker"people.Add(_Person)_Person.PersonName = "Sir Real"people.Add(_Person)lstBox1.ItemsSource = peopleEnd SubEnd Class And the matching XAML for this Binding is as follows Binding To Collections In XAML The 2nd ListBox has its ItemSource set in XAML as follows: You can see that we have an instance of the People object directly in the XAML, within a resources section, and that the declared People object has several children of type Person. This is all thanks to the XAML parser which knows that children should be added using the Add() method of the ObserverableCollection. I should point out that these examples are merely demonstrating how to Bind to collections. Probably in a production system, the collection would be part of a BAL layer/ or maybe part of a model within a MVC/MVVM pattern. Im going for quick an dirty to get the point across. One other thing that I would like to bring your attention to is the rendering of the items within the ListBox. See how they simply show "BindingToCollection.Persons", as plain text. This is obviously not the desired effect, but happens because WPF does not know what properties to show and how they should be shown for a Person object. This will be the subject of my next article Templates. I wont write any more about this, but just know that we can change the way a data item looks using a DataTemplate. If you really can't wait you can have a look at these links MSDN : DataTemplatingJosh Smith : A Guided Tour of WPF - Part 4 (Data templates and triggers) NOTE : As I stated earlier I did not cover grouping/sorting/filtering etc etc, and if you really want to know more about these, please use the links provided at the start of this article. Imagine a situation where we have a bound data value that we wish to format in some way, say by using a short date format instead of a long date fomat. Up until now we have simply used the raw Binding value. So this wouldnt be possible, we would have to make sure the bound value had what we want to display. Luckily WPF has a trick up its sleeve, we can use a class that implements theIValueConverter interface to provide a new value for the binding. ValueConverters are like the sprintf of the WPF world. You can use a ValueConverter to literally provide a new object to a Binding. This may be an object of the same type as the orginal object, or could be a totally new object. For example in WPF there is a principle of aFreezable Object which is an imutable object. If you try and animate a Frozen object, you will have problems. I have in the past circumnaviagted this issue with using a Clone ValueConverter to provide a cloned object to a Binding which is then used in an animation. But more typically you may use ValueConverters for small formatting changes. ValueConverters sit between the source value and the bound target property, and their sole purpose is so take a value and supply a different value. TheIValueConverter interface contains the following methods that must be implemented. object Convert(object value, Type targetType, object parameter, CultureInfo culture) Which is used to convert from the source object into the new value which will be used by the target object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) Which is used to convert from the target object back to the source. This will be used where a BindingsBinding.Mode has been set to TwoWay or OneWayToSource. More often than not this will not be used and will simply throw an exception. So how do we use of of these ValueConverters in our code. Well quite simply we use the normal Bindings expression but we also state which converter to use for the Binding.Converter property. Lets see an example shall we. As part of the demo solution, you will find a project entitled "ValueConverters" which when run, will look like the following: This small example actually uses 2 ValueConverters, the top one converts from words to a Brush that is used to color a Rectangle. The 2nd value converter uses an explicitly set DataContext in the code behind where 2 labels have their DataContext set to a new DateTime. Lets see the code First the XAML And here is the code behind for this Window using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;namespace ValueConverters{/// /// Interaction logic for Window1.xaml/// public partial class Window1 : Window{public Window1(){InitializeComponent();lblLongDate.DataContext = new DateTime();lblShortDate.DataContext = new DateTime();}}} And finally the converters using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows.Data;using System.Windows.Media;using System.Globalization;namespace ValueConverters{[ValueConversion(typeof(String), typeof(SolidColorBrush))]public class WordToColorConverter : IValueConverter{public object Convert(object value, Type targetType,object parameter, CultureInfo culture){string boundWord = value as string;SolidColorBrush returnBrush = null;switch (boundWord.ToLower().Trim()){case "hot":returnBrush = new SolidColorBrush(Colors.Red);break;case "cold":returnBrush = new SolidColorBrush(Colors.Green);break;default:returnBrush = new SolidColorBrush(Colors.Yellow);break;}return returnBrush;}public object ConvertBack(object value, Type targetType,object parameter, CultureInfo culture){throw new Exception("Cant convert back");}}}using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows.Data;using System.Windows.Media;using System.Globalization;namespace ValueConverters{[ValueConversion(typeof(DateTime), typeof(String))]public class DateConverter : IValueConverter{public object Convert(object value, Type targetType,object parameter, CultureInfo culture){DateTime date = (DateTime)value;return date.ToShortDateString();}public object ConvertBack(object value, Type targetType,object parameter, CultureInfo culture){string strValue = value.ToString();DateTime resultDateTime;if (DateTime.TryParse(strValue, out resultDateTime)){return resultDateTime;}return value;}}} And here are the VB .NET versions, code behind Imports SystemImports System.Collections.GenericImports System.LinqImports System.TextImports System.WindowsImports System.Windows.ControlsImports System.Windows.DataImports System.Windows.DocumentsImports System.Windows.InputImports System.Windows.MediaImports System.Windows.Media.ImagingImports System.Windows.NavigationImports System.Windows.Shapes''' ''' Interaction logic for Window1.xaml ''' Partial Public Class Window1Inherits WindowPublic Sub New()InitializeComponent()lblLongDate.DataContext = New DateTime()lblShortDate.DataContext = New DateTime()End SubEnd Class VB .NET converters Imports SystemImports System.Collections.GenericImports System.LinqImports System.TextImports System.Windows.DataImports System.Windows.MediaImports System.Globalization _Public Class WordToColorConverterImplements IValueConverterPublic Function Convert(ByVal value As Object, ByVal targetType As Type,ByVal parameter As Object, ByVal culture As CultureInfo)As Object Implements IValueConverter.ConvertDim boundWord As String = TryCast(value, String)Dim returnBrush As SolidColorBrush = NothingSelect Case boundWord.ToLower().Trim()Case "hot"returnBrush = New SolidColorBrush(Colors.Red)Exit SelectCase "cold"returnBrush = New SolidColorBrush(Colors.Green)Exit SelectCase ElsereturnBrush = New SolidColorBrush(Colors.Yellow)Exit SelectEnd SelectReturn returnBrushEnd FunctionPublic Function ConvertBack(ByVal value As Object, ByVal targetType As Type,ByVal parameter As Object, ByVal culture As CultureInfo)As Object Implements IValueConverter.ConvertBackThrow New Exception("Cant convert back")End FunctionEnd ClassImports SystemImports System.Collections.GenericImports System.LinqImports System.TextImports System.Windows.DataImports System.Windows.MediaImports System.Globalization _Public Class DateConverterImplements IValueConverterPublic Function Convert(ByVal value As Object, ByVal targetType As Type,ByVal parameter As Object, ByVal culture As CultureInfo)As Object Implements IValueConverter.ConvertDim [date] As DateTime = DirectCast(value, DateTime)Return [date].ToShortDateString()End FunctionPublic Function ConvertBack(ByVal value As Object, ByVal targetType As Type,ByVal parameter As Object, ByVal culture As CultureInfo)As Object Implements IValueConverter.ConvertBackDim strValue As String = value.ToString()Dim resultDateTime As DateTimeIf DateTime.TryParse(strValue, resultDateTime) ThenReturn resultDateTimeEnd IfReturn valueEnd FunctionEnd Class NOTE : I did not coverMultiBinding because Josh Smith does such a great job of covering this in his excellentarticle, that I didn't feel there was any need to write more about this. So far we've looked at binding to values/other elements/xml etc etc and seen how we can convert values. Which is good. But one of the main concerns of using Binding is validating what data is entered, especially when we have aBinding.Mode property set to TwoWay or OneWayToSource. We really need to make sure that we only allow valid data to be sent back to a source object. Not only is it the right thing to do, but it ensures that we dont send back rubbish data to our persistence store (database/file etc etc). So how are we going to do that we need some sort of validation applied to our Bindings. Luckily Microsoft knew about this and have equipped us with the nessecary ammunition to create good well behaved validated Databindings. There are 3 main way that validation may be performed and we shall have a look at each of them below. As part of the demo solution, you will find a project entitled "Validation" which when run, will look like the following: Visual Validation Changes As part of the attached "Validation" project, I have had include some Styles. Which is an area that we have not yet covered. There is no way out of this. The things you need to know for the moment are that a TextBox entry that is invalid will cause the associated TextBox to have its visual appearance changed by the use of a Style or a Template. And the other thing is how the TextBox.ToolTip is showing the correct validation message. Well this is also done via some clever binding, which is as follows: As I say I dont want to get to bogged down with Styles/Templates as they are the discussion of the next article, but I think that this one element deserves a mention. Exception Based Validation Probably the easist way to use validation in Binding is to use the Exception based validation rule. Which basically means if an Exception is seen while trying to update a bound property, we can use the Exception to inform the user. Typically this would be done by showing a message on a tooltip, and changing the TextBox visual as previously discussed. If we have a small test class to bind to as follows: using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Validation{public class TestClass{public int Age { get; set; }public DateTime StartDate { get; set; }public TestClass(){StartDate = DateTime.Now;}}} And here is the VB .NET version Imports SystemImports System.Collections.GenericImports System.LinqImports System.TextPublic Class TestClassPrivate m_Age As Integer = 1Private m_StartDate As DateTimePublic Property Age() As IntegerGetReturn m_AgeEnd GetSet(ByVal value As Integer)m_Age = valueEnd SetEnd PropertyPublic Property StartDate() As DateTimeGetReturn m_StartDateEnd GetSet(ByVal value As DateTime)m_StartDate = valueEnd SetEnd PropertyPublic Sub New()m_StartDate = DateTime.NowEnd SubEnd Class And we set the Binding up in code behind as follows (using the DataContext). using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;namespace Validation{/// /// Interaction logic for Window1.xaml/// public partial class Window1 : Window{public Window1(){InitializeComponent();this.DataContext = new TestClass();txtIDataErrorInfoAge.DataContext = new Person();txtIDataErrorInfoName.DataContext = new Person();}}} And in VB .NET Imports SystemImports System.Collections.GenericImports System.LinqImports System.TextImports System.WindowsImports System.Windows.ControlsImports System.Windows.DataImports System.Windows.DocumentsImports System.Windows.InputImports System.Windows.MediaImports System.Windows.Media.ImagingImports System.Windows.NavigationImports System.Windows.Shapes''' ''' Interaction logic for Window1.xaml ''' Partial Public Class Window1Inherits WindowPublic Sub New()InitializeComponent()Me.DataContext = New TestClasstxtIDataErrorInfoAge.DataContext = New PersontxtIDataErrorInfoName.DataContext = New PersonEnd SubEnd Class Then we are able to use the Exception based validation as follows in the XAML! The important thing to note is that the Binding.ValidatesOnExceptions=True this means that the WPF inbuilt ExceptionValidationRule will be used to create the appropraite validation message that will be shown in the TextBox.Tooltip Custom ValidationRules Based Validation Custom ValidationRules is similar in principle to the inbuilt ExceptionValidationRule but this time we are using our own ValidationRule to create the appropriate validation messages. Here is an example of a custom ValidationRule, where the value entered for the binding must be a DateTime in the future. using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows.Controls;using System.Globalization;namespace Validation{class FutureDateValidationRule : ValidationRule{public override ValidationResult Validate(object value, CultureInfo cultureInfo){DateTime date;try{date = DateTime.Parse(value.ToString());}catch (FormatException){return new ValidationResult(false, "Value is not a valid date.");}if (DateTime.Now.Date > date){return new ValidationResult(false, "Please enter a date in the future.");}else{return ValidationResult.ValidResult;}}}} And here is the VB .NET version Imports SystemImports System.Collections.GenericImports System.LinqImports System.TextImports System.Windows.ControlsImports System.GlobalizationPublic Class FutureDateValidationRuleInherits ValidationRulePublic Overloads Overrides Function Validate(ByVal value As Object,ByVal cultureInfo As CultureInfo) As ValidationResultDim [date] As DateTimeTry[date] = DateTime.Parse(value.ToString())Catch generatedExceptionName As FormatExceptionReturn New ValidationResult(False, "Value is not a valid date.")End TryIf DateTime.Now.[Date] > [date] ThenReturn New ValidationResult(False, "Please enter a date in the future.")ElseReturn ValidationResult.ValidResultEnd IfEnd FunctionEnd Class And we set the Binding up in code behind as follows (using the DataContext). using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;namespace Validation{/// /// Interaction logic for Window1.xaml/// public partial class Window1 : Window{public Window1(){InitializeComponent();this.DataContext = new TestClass();txtIDataErrorInfoAge.DataContext = new Person();txtIDataErrorInfoName.DataContext = new Person();}}} And in VB .NET Imports SystemImports System.Collections.GenericImports System.LinqImports System.TextImports System.WindowsImports System.Windows.ControlsImports System.Windows.DataImports System.Windows.DocumentsImports System.Windows.InputImports System.Windows.MediaImports System.Windows.Media.ImagingImports System.Windows.NavigationImports System.Windows.Shapes''' ''' Interaction logic for Window1.xaml ''' Partial Public Class Window1Inherits WindowPublic Sub New()InitializeComponent()Me.DataContext = New TestClasstxtIDataErrorInfoAge.DataContext = New PersontxtIDataErrorInfoName.DataContext = New PersonEnd SubEnd Class Then we are able to use this custom FutureDateValidationRule in the XAML! The important thing to note here is that because we needed to add a new FutureDateValidationRule to the Binding.ValidationRules, we needed to use the Property as Elements syntax. .NET 3.5 way Using IDataErrorInfo With the release of .NET 3.5 came LINQ, oh and also a few improvements to WPF. One of which is a new interface calledIDataErrorInfo which shifted where some of the validation was performed. It moved it from seperate validation classes back into the actual business object themselves. Lets see an example of a simple class that implements theIDataErrorInfo interface. using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.ComponentModel;namespace Validation{/// /// This is the new .NET 3.5 method where each Business Object has its own validation/// using the IDataErrorInfo interface/// public class Person : IDataErrorInfo{public int Age { get; set; }public string Name { get; set; }public Person(){this.Age = 0;this.Name = "sacha";}#region IDataErrorInfo Memberspublic string Error{get{return null;}}/// /// Examines the property that was changed and provides the/// correct error message based on some rules/// /// The property that changed/// a error message string public string this[string name]{get{string result = null;//basically we need one of these blocks for each property you wish to validateswitch (name){case "Age":if (this.Age < 0 || this.Age > 150){result = "Age must not be less than 0 or greater than 150.";}break;case "Name":if (this.Name == string.Empty){result = "Name can't be empty";}if (this.Name.Length > 5){result = "Name can't be more than 5 characters";}break;}return result;}}#endregion}} And here is the VB .NET version Imports SystemImports System.Collections.GenericImports System.LinqImports System.TextImports System.ComponentModel''' ''' This is the new .NET 3.5 method where each Business Object has its own validation ''' using the IDataErrorInfo interface ''' Public Class PersonImplements IDataErrorInfoPrivate m_Age As IntegerPrivate m_Name As StringPublic Property Age() As IntegerGetReturn m_AgeEnd GetSet(ByVal value As Integer)m_Age = valueEnd SetEnd PropertyPublic Property Name() As StringGetReturn m_NameEnd GetSet(ByVal value As String)m_Name = valueEnd SetEnd PropertyPublic Sub New()Me.Age = 0Me.Name = "sacha"End Sub#Region "IDataErrorInfo Members"Public ReadOnly Property [Error]() As String Implements System.ComponentModel.IDataErrorInfo.ErrorGetReturn NothingEnd GetEnd Property''' ''' Examines the property that was changed and provides the ''' correct error message based on some rules ''' ''' The property that changed ''' a error message string Default Public ReadOnly Property Item(ByVal Name As String)As String Implements System.ComponentModel.IDataErrorInfo.Item'Default Public ReadOnly Property Item(ByVal name As String) As StringGetDim result As String = Nothing'basically we need one of these blocks for each property you wish to validate Select Case NameCase "Age"If Me.Age < 0 OrElse Me.Age > 150 Thenresult = "Age must not be less than 0 or greater than 150."End IfExit SelectCase "Name"If Me.Name = String.Empty Thenresult = "Name can't be empty"End IfIf Me.Name.Length > 5 Thenresult = "Name can't be more than 5 characters"End IfExit SelectEnd SelectReturn resultEnd GetEnd Property#End RegionEnd Class Basically the interface allows us to validate the property that changed using the public string this[string name] syntax. The XAML is a little different this time, where the Binding no longer needs to use a seperate validation class, so we can simply use the shorthand XAML syntax, the one with the { } braces. Again if you prefer the longer more verbose syntax you can do that also. Notice that this time we have set the Binding.ValidatesOnDataErrors=True this means that the DataErrorValidationRule will be included, which uses the IDataErrorInfo implementation we discussed. WARNING : Beware of Tabs I recently got a rather cool email from Karl Shifllet warning of a bug with validation error disappearing when you use tabs in WPF. You should familiarise yourself with Karlsblog entry about this. We're Done There is more to Databinding than I have covered here, for example I have not covered grouping/sorting/filtering etc etc, and ther will be databinding points and syntax that I have missed. I leave these areas as an excercise for the reader. This article was meant as an introduction to Databinding, hope you enjoyed it. If you liked it, please vote for it and leave a comment, and maybe read the next article in this series. Thanks MSDN : Databinding overviewMSDN : MultibindingMSDN : Binding classData Validation In .NET 3.5Bind to XML Data Using an XMLDataProvider and XPath Queries Beatriz "The Binding Queen" Costa : BlogJosh Smith : A Guided Tour of WPF – Part 3 (Data binding) 14/02/08 : Initial release License This article, along with any associated source code and files, is licensed underThe Code Project Open License (CPOL)