Good-bye OnPropertyChanged. Hello BindableProperty

One of the most annoying things with XAML binding in WPF and Windows App Store apps is the need to raise a property changed notification to the user interface. Typically, you would abstract the actual property changed notification in to a base class like this:

public class BindableBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void SetProperty<T>(ref T oldValue, T newValue, [CallerMemberName] string property = "")
    {
        if (object.Equals(oldValue, newValue))
        {
            return;
        }

        oldValue = newValue;
        this.OnPropertyChanged(property);
    }

    protected virtual void OnPropertyChanged(string property)
    {
        var eventHandler = this.PropertyChanged;
        if (eventHandler != null)
        {
            eventHandler(this, new PropertyChangedEventArgs(property));
        }
    }
}

This at least prevents you from having to implement INotifyPropertyChanged on every one of your models. The issue however is that you still need to raise the event. In order to do so, you would invoke the base class' OnPropertyChanged method.

public class User : BindableBase
{
    private string firstName;

    private string lastName;

    public string FirstName
    {
        get
        {
            return this.firstName;
        }
        set
        {
            this.SetProperty(ref this.firstName, value);
        }
    }

    public string LastName
    {
        get
        {
            return this.lastName;
        }

        set
        {
            this.SetProperty(ref this.lastName, value);
        }
    }
}

The boiler plate code here gets really monotonous when you have a project with more than a handful of models. Luckily, Roslyn now has Initializer support for Auto-Properties..

With Auto-Property Initializers, we can build a wrapper around the actual property and bind to the value our wrapper holds. To demonstrate, we will create a simple wrapper. There will be a generic and a non-generic flavor. The non-generic provides a static method for constructing a generic wrapper. We will call this wrapper BindableProperty.

Generic Property Wrapper

public class BindableProperty<T> : BindableBase
{
    private T value;

    public BindableProperty(T value, [CallerMemberName] string propertyName = "")
    {
        this.value = value;
        this.Name = propertyName;
    }

    public BindableProperty([CallerMemberName] string propertyName = "")
    {
        this.value = default(T);
        this.Name = propertyName;
    }

    public T Value
    {
        get
        {
            return this.value;
        }

        set
        {
            this.SetProperty(ref this.value, value);
        }
    }

    public string Name { get; private set; }

    public static BindableProperty<T> Prepare(T value, [CallerMemberName] string propertyName = "")
    {
        return new BindableProperty<T>(value, propertyName);
    }

    public static BindableProperty<T> Prepare([CallerMemberName] string propertyName = "")
    {
        return new BindableProperty<T>(default(T), propertyName);
    }
}

Non-generic static class for coonstruction

public static class BindableProperty
{
    public static BindableProperty<T> Prepare<T>([CallerMemberName] string propertyName = "")
    {
        return new BindableProperty<T>(default(T), propertyName);
    }
}

You can see the BindableProperty object still has a private backing field and a property setter that handles the property changed event. The difference however is that this is the only place this code needs to ever exist now.

With our new BindableProperty object, let's re-write our User.

public class User
{
    public BindableProperty<string> FirstName { get; set; } = BindableProperty.Prepare<string>();

    public BindableProperty<string> LastName { get; set; } = BindableProperty.Prepare<string>();
}

We now have properties in our model that can be data-bound to and push change notifications back to the UI. We could even provide an initial value for the properties if we wanted to.

public class User
{
    public BindableProperty<string> FirstName { get; set; } = BindableProperty.Prepare<string>(string.Empty);

    public BindableProperty<string> LastName { get; set; } = BindableProperty.Prepare<string>("Stevenson");
}

Now we can create a view model real-quick for our view.

public class NewUserViewModel : ICommand
{
    public User NewUser { get; set; } = new User();

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public async void Execute(object parameter)
    {
        if (string.IsNullOrEmpty(this.NewUser.FirstName.Value) ||
            string.IsNullOrEmpty(this.NewUser.LastName.Value))
        {
            var dlg = new MessageDialog("User information is invalid");
            await dlg.ShowAsync();
        }
    }
}

In order to execute properly, the FirstName and LastName properties need to have their Value property checked. If the Value property is null, we show a dialog. Having to check the Value property is an extra step that you wouldn't normally need to take, but one extra 'dot' is a lot less than having to write all the OnPropertyChanged boiler plate code.

Now for our view, we just wire up a quick simple user entry form. The TextBoxes are bound to the Value property in each of the User's BindableProperty properties.

<StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="First name" />
        <TextBox Text="{Binding Path=NewUser.FirstName.Value}" />
    </StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Last name" />
        <TextBox Text="{Binding Path=NewUser.LastName.Valuey}" />
    </StackPanel>

    <Button Command="{Binding }"
            Content="Create." />
</StackPanel>

This is going to make your models a lot cleaner and speed up the amount of time it takes to create property changed based objects.

Building an Exception Factory

If you write a lot of code that takes dependencies in a method or constructor, you'll find that you write a lot of null checking like this:

public DefaultGame(ILoggingService loggingService, IWorldService worldService)
{
    if (loggingService == null)
    {
        throw new ArgumentNullException("loggingService", "Logging Service must not be null!");
    }
    else if (worldService == null)
    {
        throw new ArgumentNullException("worldService", "World Service must not be null!");
    }

    this.loggingService = loggingService;
    this.worldService = worldService;
}

Depending on the number of dependencies, this tends to bloat methods with more safety checks than actual code. I wanted to resolve this, and did so with a factory.

The factory needed to satisfy a few things.

  • Instance exceptions
  • Support stashing custom data in to the exceptions
  • Only throw if a given condition was met
  • Allow a callback if the conditions are not met (meaning no exception will be thrown)

Turns out this was pretty easy to implement. The end product, in its simplest form looks like this:

public DefaultGame(ILoggingService loggingService, IWorldService worldService)
{
    ExceptionFactory
        .ThrowExceptionIf< ArgumentNullException>(loggingService == null);
    ExceptionFactory
        .ThrowExceptionIf< ArgumentNullException>(worldService == null);

    this.loggingService = loggingService;
    this.worldService = worldService;
}

You can also invoke a callback, and provide a custom message.

public DefaultGame(ILoggingService loggingService, IWorldService worldService)
{
    ExceptionFactory
        .ThrowExceptionIf< ArgumentNullException>(loggingService == null, "Logging Service must not be null!")
        .ElseDo(() => this.loggingService = loggingService);

    ExceptionFactory
        .ThrowExceptionIf< ArgumentNullException>(worldService == null, "World Service must not be null!")
        .ElseDo(() => this.worldService = worldService);
}

If you need to do something more complex with your conditional check, you use a Func< bool>

ExceptionFactory
    .ThrowExceptionIf< Exception>(
        () =>
        {
            this.Worlds = worldService.GetAllWorlds();
            return this.Worlds.Any();
        },
        "An empty world can not be used!"));

It also supports providing a custom exception factory method for use. Since some exceptions have additional parameters in the constructor, this can be really useful.

ExceptionFactory
    .ThrowExceptionIf< ArgumentNullException>(
        worldService == null,
        () => new ArgumentNullException("worldService", "World Service must not be null!"));

We can also pass custom data in to the exception if we want.

ExceptionFactory
    .ThrowExceptionIf< ArgumentNullException>(
        worldService == null,
        () => new ArgumentNullException("worldService", "World Service must not be null!"),
        new KeyValuePair< string, string>("Member", "DefaultGame"),
        new KeyValuePair< string, string>("MemberType", "Constructor"));

So how does the insides work? Let's take a look

The Factory

There are a total of four factory methods.

  • ThrowExceptionIf< TException>(Func< bool> predicate, string message = null, params KeyValuePair< string, string>[] data);
  • ThrowExceptionIf< TException>(Func< bool> predicate, Func< TException> exception, params KeyValuePair< string, string>[] data)
  • ThrowExceptionIf< TException>(bool condition, string message = null, params KeyValuePair< string, string>[] data)
  • ThrowExceptionIf< TException>(bool condition, Func< TException> exception, params KeyValuePair< string, string>[] data)

and one last method for adding data to the exception

AddExceptionData(Exception exception, params KeyValuePair< string, string>[] data)

Since we can build this in an overloaded fashion, we will just build the most complex method out, then let the rest of them piggy back on top of it.

public static ExceptionFactoryResult ThrowExceptionIf< TException>(bool condition, Func< TException> exception, params KeyValuePair< string, string>[] data) where TException : Exception, new()
{
    if (condition)
    {
        return new ExceptionFactoryResult();
    }

    TException exceptionToThrow = exception();
    AddExceptionData(exceptionToThrow, data);

    throw exceptionToThrow;
}

This method is really straight forward, it requires a bool value to indicate if this exception must be instanced and thrown or not. If the condition is false, then we go ahead and invoke the Func< TException> delegate. This returns the exception that we are to throw.

Next we take the optional exception data parameter and pass it to an AddExceptionData method. That method will iterate over the param data and add it to the exception. We then finally throw the exception. Really straight forward.

The AddExceptionData method looks like this:

public static void AddExceptionData(Exception exception, params KeyValuePair< string, string>[] data)
{
    foreach (var exceptionData in data)
    {
        exception.Data.Add(exceptionData.Key, exceptionData.Value);
    }
}

Now we can build out our overloads. The second most complex one is really easy to write. We just pass a delegate in that instances a new exception using the Activator class.

public static ExceptionFactoryResult ThrowExceptionIf< TException>(bool condition, string message = null, params KeyValuePair< string, string>[] data) where TException : Exception, new()
{
    return ThrowExceptionIf< TException>(
        condition,
        () => (TException)Activator.CreateInstance(typeof(TException), message),
        data);
}

Next, we will provide support for delegate predicates.

public static ExceptionFactoryResult ThrowExceptionIf< TException>(Func< bool> predicate, Func< TException> exception, params KeyValuePair< string, string>[] data) where TException : Exception, new()
{
    return ThrowExceptionIf< TException>(predicate(), exception, character, data);
}

public static ExceptionFactoryResult ThrowExceptionIf< TException>(Func< bool> predicate, string message = null, params KeyValuePair< string, string>[] data) where TException : Exception, new()
{
    return ThrowExceptionIf< TException>(predicate(), message, character, data);
}

The last thing we need to do is support the method callbacks. This is done using the ExceptionFactoryResult class that all of our factory methods return. This class has nothing more than a simple method that takes an Action and invokes it.

public class ExceptionFactoryResult
{
    public void ElseDo(Action callback)
    {
        callback();
    }
}

That's all there is to it!

ValidatableBase 2.0

A couple of weeks ago I released verison 2.0 of ValidatableBase on GitHub. The newest build provides Data Annotation styled attribute validation for Universal Windows applications, iOS, Android and any other platform that .NET Portable Class Libraries can run on.

Release features

  • New Data Annotation styled attribute validation system has been added. The attributes implement IValidationRule and provide a simple means of writing custom validation rules if needed.
  • Registration of properties is no longer needed.
  • The library is now in a Portable Class Library, usable across all platforms that PCL's can run on.
    • As a side-effect of this, the validation messages collection is no longer directly exposed. The underlying implementation is Dictionary< string, IEnumerable< IValidationMessage>> which requires conversion if you need to bind to the validation results. The example app includes an extension method that can be used to perform the conversion, for view models that want to expose validation to the view.
  • ValidatableBase now has a ValidationChanged event that you can subscribe to. Any time validation is changed, either by adding/removing messages or running validation, your view models can be notified.

Validation Rule examples

ValidatableBase supports a very flexible attribute based validation system that can be used on any of your models, regardless of platform.

To demonstrate, let's create a very basic model with zero validation.

namespace SampleUniversalApp.Models
{
    using System.ComponentModel;
    using System.Linq;
    using System.Reflection;
    using Sullinger.ValidatableBase.Models;
    using Sullinger.ValidatableBase.Models.ValidationRules;

    public class User : INotifyPropertyChanged
    {
        private string email = string.Empty;

        private string password = string.Empty;

        public event PropertyChangedEventHandler PropertyChanged;

        public string Email
        {
            get
            {
                return this.email;
            }

            set
            {
                this.email = value;
                this.OnPropertyChanged("Email");
            }
        }

        public string Password
        {
            get
            {
                return this.password;
            }

            set
            {
                this.password = value;
                this.OnPropertyChanged("Password");
            }
        }

        protected virtual void OnPropertyChanged(string propertyName = "")
        {
            var handler = this.PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

This model is really straight-forward and shouldn't need any explaining. It implements INotifyPropertyChanged and has two properties.

Validation

Now that we have a model, we want to validate it. We will perform validation on both the Email and the Password properties. We want to make sure neither of them are blank.

The first thing we have to do is inherit from a concrete Type implementing IValidatable. The ValidatableBase API ships with a base class called ValidatableBase (surprise, surprise) that you can use.

Update your class definition to look like the following:

public class User : ValidatableBase, INotifyPropertyChanged

Since the ValidatableBase API is cross-platform and lives within a Portable Class Library, the ValidatableBase class does not implement INotifyPropertyChanged. If you are targeting a platform that supports this (such as WPF) then you can build a secondary base-class on top of ValidatableBase, or build your own implementation of IValidatable.

The ValidatableBase API performs validation mostly through attributes. To make sure neither property is left blank, we will decorate each property with a ValidateObjectHasValue attribute.

    [ValidateObjectHasValue(
        FailureMessage = "E-Mail can not be left blank.", 
        ValidationMessageType = typeof(ValidationErrorMessage))]
    public string Email
    {
        get
        {
            return this.email;
        }

        set
        {
            this.email = value;
            this.OnPropertyChanged("Email");
        }
    }

    [ValidateObjectHasValue(
        FailureMessage = "Password can not be left blank.",
        ValidationMessageType = typeof(ValidationErrorMessage))]
    public string Password
    {
        get
        {
            return this.password;
        }

        set
        {
            this.password = value;
            this.OnPropertyChanged("Password");
        }
    }

Performing the validation

The next step is to obviously perform the validation. To do that, we will create a view model that implements ICommand, exposing an Execute method.

public class MainPageViewModel : ICommand, INotifyPropertyChanged
{
    public MainPageViewModel()
    {
        this.AppUser = new User();
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public event EventHandler CanExecuteChanged;
    public User AppUser { get; private set; }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        // Perform validation on the user's built in validation.
        this.AppUser.ValidateAll();

        // Do stuff.
        return;
    }

We have now validated our model. You can check if the model has any validation messages (indicating failure) by using the HasValidationMessages< IValidationMessage>() method.

if (this.AppUser.HasValidationMessages< ValidationErrorMessage>())
{
    // Failed, so abort.
    return;
}

Adding additional validation rules.

Since the models validation is performed by the attributes, we can come back at a later date and add or replace validation on the properties without having to re-write a large amount of logic code. To demonstrate, we will replace the Password properties validation. Instead of checking if the property is empty, we will check if the password entered meets a required password range of 6 to 20 characters.

    [ValidateStringIsGreaterThan(GreaterThanValue = 6, 
        FailureMessage = "Password must be greater than 6 characters.", 
        ValidationMessageType = typeof(ValidationErrorMessage))]
    [ValidateStringIsLessThan(LessThanValue = 20, 
        FailureMessage = "Password must be less than 20 characters.", 
        ValidationMessageType = typeof(ValidationErrorMessage))]
    public string Password
    {
        get
        {
            return this.password;
        }

        set
        {
            this.password = value;
            this.OnPropertyChanged("Password");
        }
    }

Now when we run the this.AppUser.ValidateAll() method, the property will ensure it has a password between the range of 6 characters and 20. If not, a ValidationErrorMessage is created.

Mud Designer's first real sprint

Now that I have Mud Designer moved over to Visual Studio Online (VSO) I can start really making use of the Agile platform that VSO is built on top of. Going forward, the project will adopt the Agile methodology, with developing taking place during sprints.

The first sprint started today with three User Stories being brought in to the sprint.

  • Text File Data Storage Service
  • Character Security Permissions
  • Command Security

Text File Data Storage Service

Once this is completed, I will have the first of many data storage services created. The intent is to create a simple data store to use while I build the rest of the engine. I have other Stories for creating SQL and Cloud based services, but those are more complex. While the engine is being developed, I want to just use a simple local data store.

Character Security Permissions

This story contains the meat of the engines security framework. When completed, Permissions can be created and assigned to Roles. There will be a framework constructed for objects that need specific security permissions, to register for them.

Command Security

Pigging backing on top of the Character Security Permissions story, this will allow Commands to register for permissions they require. The engine will ensure that users have the required permissions within their roles before letting them execute the command.

Wrapping up

Since I am the only developer, each sprint is scheduled for 4 weeks, so it will be a bit before this sprint is completed. If the user stories are finished early, I will pull more stories in and continue working until the end of the sprint.

As each story is completed, I plan on writing a post on what work was done and what the features are. I would also like to do a code analysis and report the quality of the code for each story.

Mud Designer Migrated to Git

I have been really wanting to use the Visual Studio Online (VSO) service for a while now with Mud Designer. I have been holding back primarily because Mud Designer is open source, while VSO is meant for closed-source team projects. TFS doesn't come with an easy way of maintaining two repositories of the same code-base, while maintaining the version history of the source.

The solution to this was Git, but the Codeplex project was hosted on a TFS instance. I then discovered - (thanks to Richard Banks for answering my Stackoverflow post) - that the Codeplex team could convert my project to a Git repository. I promptly fired them an e-mail and had my project converted.

Now that Mud Designer was sitting in a Git project, I cloned it to VSO. Now any time I push changes to VSO, I can simultaneously push changes to Codeplex. This lets me make use of VSO's Agile work items, such as User Stories, sprints and bug tracking, while keeping the source freely available to the public. Win win!