Thursday, August 2, 2012

Portable Class Library & MVVM

This is continued from the previous post where we introduced Portable Library Tools from Microsoft. In this post we will be discussing how useful portable library tools are for the incorporation of MVVM for an application which have multiple UI requirements. The application can be consumed by users from different platforms. These might include Silverlight, WPF, Windows Phone and now Metro. Since all of these platforms can be developed in XAML, we don't need to find many developers with platform specific expertise to develop for a particular platform, keeping in mind that the XAML might be closely similar but same XAML cannot be used for these platforms. It might have a different class hierarchy, different defaults and non-matching behaviors. This also helps in shuffling developers across these teams.

Based on the above discussion, we cannot use same view for these platforms. Back in the days, we couldn't even share the view model across these platforms as many MVVM specific features are not available across these platforms, Or they are not provided similarly. With .Net 4.5 and portable libraries, this gap is being minimized. The features available in one platform is being available in the other platform. It's example is INotifyDataErrorInfo. This used to be available only in Silverlight platform. This is used to notify the errors to the interested UI logic. With .net framework 4.5 Developer's preview, this has been incorporated in .net framework. Before this, we weren't able to share the same view models from silverlight to .net framework because of same reason. Even if we minimize the features to better incorporate multitargeting, we still couldn't use the same assembly across these platforms as the assembly is compiled differently across these frameworks.

Portable Libraries make our lives easier by making only those features available which are supported by all of the selected platforms. If we are targeting our libraries for .net framework 4.5 and Silverlight 4 then only those features would be available which are available in both of these platforms. Let's try to understand this with an example. We are using the same concept of CoffeeHouse application as we have been using for a while. But in order to minimize the noise, we are tasked with a simple interface to enter Barista's information. We only need to provide the details about First and Last name of Barista.

Creating Projects and Adding References
Let's first add a portable class library project for holding view models as follows:

Since this is a portable library based project, we can target multiple platforms. As per the requirement, we are selecting .net framework 4.5 and Silverlight 4 platforms.

Similarly, we add another portable library project to hold our models. This project also targets .net framework 4.5 and Silverlight 4.

Since both model and view model based projects are portable library projects targeting the same platforms, we can add the reference of one in other project. In MVVM view model can hold model's instance when model is not aware of the view model it belongs to. This is similar to Dependency Inversion idea where higher level module (view model) uses lower level modules (models). Here we are adding model project's reference to the view model project.

Now we can add WPF and Silverlight projects for UI logic.

Both of them would need a reference of view model's project so that view model types are available to the UI logic.

The project's references are added as follows:

Please notice that the Silverlight and WPF projects are using the same view model and model's libraries which is the core idea of multitargeting.

Adding Model
Let's add a simple model to Model's project to hold Barista's information. It simply has two properties to hold first and last names of Barista.

Adding View Model
Now we need to add view model. The view model needs to provide the view state. It is responsible for passing the state between view and model at appropriate time. It is also exposing properties for first and last name of the barista. It implements INotifyPropertyChanged to provide value change notification for its properties. The view would be using PropertyChanged event to update itself based on the state of the view model. It also implements INotifyDataErrorInfo for validating the view state. It is supposed to raise ErrorsChanged event whenever error state of a property is updated. The property can be updated from valid to invalid state or vice versa. It is maintaining a collection to hold error details of these properties.

The view model also exposes an ICommand, named SaveBaristaCommand. When executed, this should pass on the view state to the model.

ICommand Implementation for Portable Library Tools
Here we can provide a custom implementation of ICommand in view model's project. This has just been used from Josh's article with minor changes. See the following series of posts from Jeremy to find out how portable class library uses type forwarders to locate the definition of ICommand in a non-SL framework.

Silverlight based UI
Let's add simple interface to enter Barista's information. Let's do it first for Silverlight. It just has two TextBox (es) to enter first and last names of the barista. It also has a button, when clicked the values should be passed to the model.

While running, this should look like as follows:

WPF based Interface
Now let's add WPF based interface to the .net framework 4.5 project. As you might have noticed, the XAML is similar but not same. For silverlight, Label is not available in the framework and we need to use it from the toolkit. In order to minimize the noise there, we ended up using TextBlock(s). Additionally, the default binding Mode is OneWay in Silverlight. Since we need TwoWay binding, we needed to explicitly specify so. We don't need this specification for WPF based XAML as the default here is TwoWay. When you run it, you might miss the error message which is available in Silverlight. this appears when INotifyDataErrorInfo specifies the presence of error for a property. Although the control is highlighted in WPF, we need to provide additional logic to display the actual error message(s).

When executed, this should look like as follows [This is similar to the Silverlight based UI]:

Existing MVVM Frameworks and Toolkits
Although it would be a big relief for most of the developers who are maintaining different versions of their libraries for specific platforms. If they were already writing multitarget enabled code, then they were still using the features which were overlapping across these frameworks. With Portable library tools, this has been taken care for them. We would just need to maintain one set of libraries which support multi-targeting for the selected platforms.

The only caveat is the already existing MVVM frameworks and toolkits which are used heavily for our MVVM designs. Since Portable libraries can only reference other portable libraries supporting the selected frameworks so we wouldn't be able to use the existing frameworks and libraries. As for our code, we needed to provide our own implementation of ICommand [RelayCommand]. Since the portable feature is so promising, I am sure that the frameworks and toolkits authors are already thinking about it.

Download Code

No comments: