Validating Properties in Silverlight Classes

Silverlight classes rely on the INotifyPropertyChanged interface and associated PropertyChanged event it contains to ensure that data binding stays up-to-date in an application.  It’s a great feature because you don’t have to worry about ensuring that changes to object properties are propagated back to controls….Silverlight handles refreshing control values for you automatically as long as the class that’s being data bound implements INotifyPropertyChanged and property set blocks raise the event.  I use a fairly standard pattern for defining my properties and raising property changed events (there are several options for doing this…see a nice list here).  Here’s an example of a property:

public Job CurrentJob
{
    get
    {
        return _CurrentJob;
    }
    set
    {
        if (value != _CurrentJob)
        {
            _CurrentJob = value;
            OnPropertyChanged("CurrentJob");
        }
    }
}


The problem is that I tend to change property names from time to time within an application and use the Visual Studio refactor feature to do it.  This works great for changing the property name or field name but doesn’t change the quoted value passed to OnPropertyChanged.  I’ve run into a few issues where I missed renaming the string value and decided that I needed to be more proactive with validating the value.  I ended up going with the following validation code after looking at a few options:

protected void OnPropertyChanged(string propertyName)
{
    CheckPropertyExists(propertyName);

    if (this.PropertyChanged != null)
    {
        this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

[Conditional("DEBUG")]
private void CheckPropertyExists(string propertyName)
{
    Type type = this.GetType();
    if (type.GetProperty(propertyName) == null)
    {
        string errorMessage = string.Format("Invalid property found: {0} in {1}", propertyName, type.FullName);
        Debug.Assert(false, errorMessage);
    }
}


Originally I used #if..#endif statements to conditionally add or take out the CheckPropertyExists method until I came across a nice post by Josh Smith where he used the Conditional attribute in a WPF application.  If you’re new to it, the compiler will leave CheckPropertyExists in the compiled code if you’re in debug mode.  If you switch to release mode it’ll take it out which is good since at that point you wouldn’t want to slow down the application with the reflection statements. 

With the CheckPropertyExists method in place I now have an easy way to know if I missed renaming a property value that’s passed to OnPropertyChanged which saves a few headaches.  I put the code in my ViewModelBase class so I only have to write it once and have it available for just about everything I do in Silverlight.  Here’s the message that I get if there’s a problem:

image

Update:  The same day I posted this I ran into a mis-named property.  The assert message popped up and I fixed it within a matter of seconds instead of searching through the code for minutes (or longer) to locate the problem. 

 

Logo

For more information about onsite, online and video training, mentoring and consulting solutions for .NET, SharePoint or Silverlight please visit http://www.thewahlingroup.com/.

 

comments powered by Disqus

2 Comments

  • Hi Dan,

    You might want to take a look at this custom tool for VS created by Daniel Cazzulino,

    http://www.codeplex.com/clarius/Release/ProjectReleases.aspx?ReleaseId=7358

    It generates a partial class file implementing INotifyPropertyChange as well as a strongly-typed event for each property declared in the file it's applied to. There is no need to use magic string anymore with that tool.

    Regards,
    Pablo.

  • One issue we've been having with Silverlight auto validation is when using WCF proxy-generated objects (that you're not supposed to change since they'll get overwritten every time the service reference is updated).

    Does anyone have any good ideas on how to validate form data from _outside_ the object for scenarios like this? Simply accessing the raw form controls doesn't seem to work (yeah, I know - old WinForms habit that probably doesn't apply anymore) - we can't seem to read the new data this way.

    Any help appreciated.

Comments have been disabled for this content.