Dear visitor, thanks for stopping by! If you want, you can follow all updates on Snowball.be via RSS. You can also follow me on Twitter or Facebook. More interesting posts from other Microsoft Regional Directors can be found at The Region.
Gill Cleeren     .net | Silverlight | Silverlight Advent Calendar | sl4     December 18, 2009    

After looking at Twitter yesterday, we have arrived at another data binding-related feature new in Silverlight 4, namely the support for the IDataErrorInfo interface.

The fact that Silverlight supports this interface now, means we can fully use it to help with the display of validation errors in a data binding scenario. The interface itself is quite simple, as shown below:

public interface IDataErrorInfo
{
    string Error { get; }
 
    string this[string columnName] { get; }
}

When we are binding an object of a class that implements the IDataErrorInfo, Silverlight will automatically check each field for validation errors using the indexer. In here, we can write validation code that will check if the specified value is valid and if not, return the error message for that field. Silverlight will then automatically display the error for the field.

I have created a small sample that does exactly that. Being it almost Christmas, I have created a sample where the user can enter his christmas music collection, as shown below.

image

The type we are binding to is called ChristmasSong. This class implements both the INotifyPropertyChanged and the IDataErrorInfo interfaces. Both have been implemented in the code below. In the indexer, we are checking per column if the entered value is valid. If not, we are returning a message containing the validation error. Note that when we are entering “Last Christmas” by “Wham”, the application will not accept it! (Sorry to all Wham fans ;-) )

public class ChristmasSong : IDataErrorInfo, INotifyPropertyChanged
{
    private string title;
    private string performedBy;
    private TimeSpan duration;
    private DateTime published;
 
    private string error;
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
 
    public string Title
    {
        get
        {
            return title;
        }
        set
        {
            title = value;
            NotifyPropertyChanged("Title");
        }
    }
 
    public string PerformedBy
    {
        get
        {
            return performedBy;
        }
        set
        {
            performedBy = value;
            NotifyPropertyChanged("PerformedBy");
        }
    }
 
    public TimeSpan Duration
    {
        get
        {
            return duration;
        }
        set
        {
            duration = value;
            NotifyPropertyChanged("Duration");
        }
    }
 
    public DateTime Published
    {
        get
        {
            return published;
        }
        set
        {
            published = value;
            NotifyPropertyChanged("Published");
        }
    }
 
    public string Error
    {
        get { return error; }
    }
 
    public string this[string columnName]
    {
        get 
        {
            string error = string.Empty;
            switch (columnName)
            {
                case "Title":
                    if(string.IsNullOrEmpty(title))
                        error = "Title can not be blank";
                    break;
                case "PerformedBy":
                    if(string.IsNullOrEmpty(performedBy))
                        error = "The artist should be filled in";
                    else if(performedBy.Equals("Wham") && title.Equals("Last Christmas"))
                        error = "You should NOT be entering that song to your collection!";
                    break;
                case "Duration":
                    if(duration.TotalSeconds > 600)
                    error = "A song can not be longer than 10 minutes";
                    break;
                case "Published":
                    if (Published > new DateTime(2010, 1, 1))
                        error = "You found a song from the future?";
                    else if (published < new DateTime(1900, 1, 1))
                        error = "That's a bit too old, isn't it?";
                    break;
            }
            return error;
        }
    }
}

We can now bind our UI to an instance of this type. Below is the XAML code for the Grid containing the fields. Note especially the data binding expression, where I’m stating the fields should be reporting the error back. For spacing reasons, I only pasted the Title field, the others are similar.

<TextBlock x:Name="TitleTextBlock" Text="Title" Grid.Row="1"  
  Foreground="Red" HorizontalAlignment="Left" Margin="2" 
  VerticalAlignment="Center"></TextBlock>
<TextBox x:Name="TitleTextBox" Grid.Row="1" Grid.Column="1" Width="200" 
  VerticalAlignment="Center" HorizontalAlignment="Left" Margin="2" 
  Text="{Binding Path=Title, Mode=TwoWay, ValidatesOnDataErrors=True, 
    NotifyOnValidationError=True}" />

When we are entering data now, the validation will kick in whenever a validation error is encountered.

We can take it one step further though, using the BindingValidationError event, defined on FrameworkElement. This event will trigger whenever a binding error is reported by the binding source, being here the instance of the ChristmasSong class. In this event, we can through the e.Action property check if an error was added or resolved. In this particular code, I have specified that the Submit button will only become enabled when there are no more errors.

private void ChristmasSongGrid_BindingValidationError(object sender, 
  ValidationErrorEventArgs e)
{
  switch (e.Action)
  {
    case ValidationErrorEventAction.Added:
         errorsOnPage++;
         break;
    case ValidationErrorEventAction.Removed:
         errorsOnPage--;
         break;
  }
  if (errorsOnPage == 0)
    SubmitButton.IsEnabled = true;
  else
    SubmitButton.IsEnabled = false;
}

All this can be seen in action, when we are entering “Last Christmas” by “Wham”!

image

The sample code can be downloaded here: SLDataErrorInfo.zip (308.96 KB)

  Posted on: Friday, December 18, 2009 12:06:56 PM (Romance Standard Time, UTC+01:00)   |   Comments [0]
         
Comments are closed.
2/7/2012   8:04:40 AM
 Welcome to Snowball.be
Hello and welcome to snowball.be!

My name is Gill Cleeren, I'm a Microsoft Regional Director and an MVP ASP.NET.
On Snowball.be, you'll find all kind news and articles on .net, ASP.NET, WPF, Silverlight and Microsoft in general.
More on me can be found on my about page.

Should you have any questions, don't hesitate to contact me by Send mail to the author(s) .

 Partner sites
 Most popular tags
.net (124) .net 3.0 (6) .net 3.5 (18) .NET 4 (18) .NET Show (1) ADO.net (4) ASP.net (53) ASP.net AJAX (4) ASP.NET MVC (3) Atlas (12) Azure (2) Blend (2) Book (5) Book review (4) C# (43) Case studies (1) Chopsticks (3) Community (10) Community Day (15) Consoles (1) Database (1) DevDays09 (4) DotNetNuke (4) Efficiency (57) Enterprise Library (5) Events (60) Expression (7) Games (3) Hardware (9) Internet (18) IT (1) jQuery (1) LightSwitch (3) Links (11) LINQ (4) Mac (2) Metro (1) Microsoft (75) Mix 07 (6) Mix 08 (4) Mix 09 (1) Mix 11 (1) Movies (4) MVP (5) MVP Summit 2008 (3) mvvm (1) Office 2007 (10) Other (8) PDC (22) PDC2008 (10) Personal (36) ppt (9) Programming (52) Programming tools (22) Regional Director (2) Silverlight (142) Silverlight Advent Calendar (24) sl4 (44) Slide decks (13) Snowball (13) Software (20) Microsoft (25) Speaking (14) SQL Server (10) TechDays (13) TechEd (14) telerik (6) Telerik (6) TFS (1) Twitter (1) Vista (73) Vista Tricks (9) Visual Studio.net (38) Visug (33) VS2010 (8) Wallpaper (2) WCF (2) Webcasts (9) Webinars (5) Windows (41) Windows 7 (5) Windows 8 (1) Windows Azure (2) Windows Mobile (3) Windows Phone 7 (2) WinFX (17) WinRT (1) WP7 (2) WPF (40) XAML (24)

 On this page
 This site
 Archives
Navigation
 Sitemap
 Blogroll OPML
 Disclaimer

All content is property of www.snowball.be. Nothing on this site can be copied or published elsewhere, unless otherwise stated.

This site is made by Gill Cleeren.

Questions? Opinions? Send mail to the author(s) E-mail