Last week, I’ve posted two series of my blog post on our upcoming ClientUI for Silverlight and WPF 4. The first series discussed about architectural overview while the second series discussed more deeply on the presentation model and the control’s development standards compliance. I highly recommend you to check them out if you haven’t done so.
The recent rising of the MVVM design pattern has created a fairly strong buzz around the community, developers and .NET shops who build RIA applications specifically for the Silverlight platform. If you’re just about getting into MVVM and stucked with conceptual difficulties and technical challenges – you’re not alone. Hundreds to thousands developers can be seen struggling with MVVM questions in one of the most popular question and answer sites. This is not very surprising as the MVVM itself currently lacks standardization from Microsoft both in implementation and toolsets.
In this third series of my blog post on ClientUI, I’ll dive deep on the MVVM architectural pattern specifically in Silverlight and how our upcoming ClientUI brings together a robust and comprehensive solution that completely addresses many challenges in adopting MVVM design pattern from both architectural and UI perspectives.
M-V-VM At A Glance
While there are numerous considerably good articles on MVVM out there, many of them are either too advanced or too conceptual which makes it difficult for beginners to understand the essence and key objectives of MVVM design pattern. I’ll try to explain MVVM in simpler way by contrasting it with the traditional ViewModel design pattern.
Common UI operations achieved with traditional ViewModel pattern.
Common UI operations achieved with modern Model-View-ViewModel pattern.
As you can see in the above illustration, MVVM is all about codes simplification with the main idea of separating the View (UI) from the logic that controls the View. The binding semantics offer an efficient way to bind two or more data entities together. When TwoWay binding is used, changes in one source will automatically propagate the changes to all data entities that bound to that changed entity thus simplifying the efforts to maintain the state of the view against the model. This is the essential key concept that enables the MVVM pattern in modern UI development platforms such as WPF and Silverlight.
The UI development technique that explained in the above illustration becomes a widely adopted pattern in software engineering which is what we called as MVVM pattern today.
That said, the true objective of MVVM pattern is to help developers writing better applications that are not only easier to maintain and extend, but also to deliver applications with greater quality in terms of stability and performance.
The following 3D illustration shows the layered MVVM implementation of a simple Contacts application which I’m going to use as the case study throughout my blog post.
Silverlight 4 and M-V-VM
Before going deeper on MVVM, it’s a good idea to see where our position stands against the recently released Silverlight 4. Let’s see what Silverlight 4 has in store.
When the first beta of Silverlight 4 was introduced in MIX two months ago, we hoped to see a more comprehensive support on MVVM implementation in the Silverlight’s core runtime. Unfortunately, Silverlight 4 did not make its way to include a full MVVM implementation in the RTM version that released last week. This is possibly understandable in the point of view that Silverlight 4 is focused more on media, devices support, out-of-browser and other UI goodies.
Although some Silverlight MVVM samples can be found in Blend 4 installation, I would prefer to say that the introduced solutions are more toward workarounds or temporary approaches as a mean to bridge the lacking of full MVVM implementation in Silverlight 4. Take a factual example, instead of using a familiar, proven WPF-style Command architecture, Silverlight 4 introduced CallMethodAction to invoke a method through reflection. See the below code snippet.
I also find it very weird that some of the new classes such as CallMethodAction and InvokeCommandAction are not available in Silverlight core runtime. Instead, they are introduced in a separate assembly called Interactivity which is surprisingly shipped only with Blend. At the most, developers would find these solutions less-than-ideal as the MVVM pattern requires a much stronger and solid architecture to avoid bottleneck and difficulties throughout the MVVM implementation.
As a third party vendor in the component industry, we’re tasked to fill in the gaps with a more solid foundation and as much as we could to deliver an end-to-end solution that aids developers building LoB applications using MVVM pattern in a more rapid and consistent manner.
A Better Solution for M-V-VM Pattern in Silverlight
As its name stands, MVVM involves implementations of three different layers, the model, the view and the view model. To correctly implement a MVVM framework, an architect requires a full understanding of MVVM concept and how the user interface layer (the view) can be easily abstracted and described through the logic (the view model). Simply put, a higher abstraction that provisions how each piece of the layer can be connected together, mainly between the view and the view model, is required to effectively produce a solid solution that supports the entire MVVM semantics and metaphors.
Ironically, there are very few MVVM solutions that satisfy both architecture and UI needs in a single box. Some well-known MVVM framework such as Unity or Caliburn are geared toward more on the architectural layer exposing several hundreds of interfaces and classes, while the others often came up with too-fancy UI goodies that don’t fully comply with the MVVM semantics. As such, developers are left with no choice but to spent weeks to months only for wiring up the architectures to the UIs and so on.
This is exactly where ClientUI comes into play. Geared toward the line-of-business and RIAs development, ClientUI is designed with a balanced set of powerful architecture and comprehensive UI toolset which sits on the top of that architecture. Therefore, it creates a higher abstraction level that makes MVVM more user-friendly to developers by hiding the complexity of the architecture. The goal is to enable developers to focus on the business logic, the presentation and user experiences that matters to their clients – not struggling with dozens of interfaces or hundreds lines of codes for the architecture stuff.
To show you the big picture of how a Silverlight application can be designed with MVVM pattern using ClientUI, I decided to write a simple Contacts case study using a similar model available in the Blend 4 sample and converts it to a more proven and best-practice MVVM pattern with ClientUI. This also enables you to compare and identify the differences between both implementations which gives you insights of the better MVVM approach for your next project.
The ClientUI-powered Contacts application demonstrates various areas of key MVVM implementation such as discussed in the following.
MVVM Contacts Sample Overview
Much like a standard LoB application, we would like several standard functionalities in our Contacts application such as presenting a list of contacts, ability to select a contact and perform edit or delete on it, and add a new contact. We would also like to have some kind of intuitive user experiences, such as showing the total contacts and the currently selected contact.
The key designs of our MVVM implementation are detailed below:
- Platform agnostic solution that enables our Contacts application to be easily reused in WPF without major codes rewriting.
- Follow MVVM principles in which actions that triggered by UI events are handled in the logic of the view model, not in the code behind of the view.
- Follow MVVM principles in which the logic in view model should be completely separated from the view. This means it’s prohibited to access UI elements directly in our view model.
- Maintain selection and view states in the view model layer which describes and controls the behaviors of the view through the effective use of two-way data binding.
- All UI elements should effectively satisfy MVVM semantics. This includes all basic form components introduced in ClientUI such as textbox, hyperlink, data listbox, toolbar, buttons, and more. In the latter sections, I’ll also explain how we support more complex UIs such as windowing, dialog box and message box to elegantly support the MVVM pattern.
The illustration below pictures our MVVM Contacts sample in overall.
Complete Command Implementation
Only with a fully implemented Command framework, developers can efficiently and rapidly address many challenges and requirements in developing MVVM application.
ClientUI includes 6 types of commands out-of-the-box. The command types such as RoutedCommand and RoutedUICommand includes a full commanding specification that matches those in WPF which leverages the power of its visual tree concept. Although mostly used in ViewModels pattern, the routed command is still one of the most frequently used approaches to achieve UI (View) related operations.
Built on the essence of WPF-style command specification, we also introduce DelegateCommand and CommandReference for MVVM pattern development. To be really useful and effective, our DelegateCommand implements automatic requery feature which sits on the top of CommandManager that powers the entire commanding framework.
One of the most common UI operations that we would like to achieve in this MVVM case study is to enable users to perform edit and delete command if a contact is selected. Likewise, the commands should be disabled from both functionality and UI aspects when there is no selection. In the application, the selection can be often modified from several sources, such as from user interaction (user clicks on the item to do a selection) or from other view model (when a new user is created). Our key objective here is to have these commands behave consistently regardless of the source that triggered the changes.
Now let’s jump into our Contacts case study and see how our DelegateCommand is used to achieve the above scenario.
The code snippet of the implementation.
The result of the implementation.
In the above image, you can notice that the Edit and Delete command are automatically enabled or disabled based on the contact selection. This behavior is also consistent when the selection is updated from any other sources that modify the selection in the view model. This is where the separation concern between the view and the view model makes a good sense in MVVM pattern.
As our DelegateCommand leverages the power of Silverlight’s visual tree through our own implementation of command manager, assigning a shortcut key to each of the command above is just a XAML declaration away. This can be easily done through CommandReference which binds each command to the respective key gesture defined in the KeyBinding. See the code below.
The art of the entire commanding implementation in MVVM is that the input binding is also a good citizen of the entire commanding semantics. That means if you pressed the Ctrl + Shift + E shortcut when the Edit command cannot be executed, the shortcut will do nothing. Likewise, you’ll see the Edit dialog box popped up when you invoke the Edit command by either clicking on the button or pressing the keyboard shortcut.
Having these commands behave consistently without writing additional codes are something UI developers have wanted for long. Rest assured you don’t want to imagine how much codes you need to write to achieve similar behavior in a traditional ViewModel pattern, or in a MVVM pattern without a solid commanding framework.
One of our key decisions to implement the DelegateCommand and CommandReference pattern in our ClientUI is that they have been well-known and widely adopted in other platforms such as WPF. That said, you can simply grab the codes above, migrate it to a WPF application and run it without major codes rewriting.
Routed Event Implementation
Routed event is one of the most fundamental components in modern client platform such as in WPF and Silverlight. ClientUI implements complete specification of routed event that matches those in WPF. As such, the ClientUI components’ architecture is built upon the three routing strategies introduced in the routed event such as tunneling, bubbling and direct.
The complete implementation of routed event is the key answer to implementing the commanding framework that I discussed above. The relation between the commanding and the routed event is that the commanding should work with input gestures and command binding, which walks through the visual tree between the original source and the listener.
In the case study that I explained in the Commanding point above, routed event is the component that works behind the scene that enables a command to be discovered when you interact with the user interface, such as pressing a keyboard shortcut in your application. In other words, the truly functional commanding framework can not be effectively achieved without a solid routed event foundation that powers it.
The next question would be how does routed event correlate to the MVVM semantics. The main idea where routed event can be useful is mostly in the scenarios where you can’t directly access the instance of UI elements.
For instance, since you shouldn’t write codes that access the view (UI) element directly from the view model, it creates complexity for developers to, say, set focus to a list box when the edit window is closed.
Routed event elegantly addresses the above scenario by allowing you to register a class level handler defined on the view layer which perfectly decouples the view logic from the element instance.
The few line of codes below shows how you can achieve the above scenario using a class handler routed event. It basically sets the focus to contact list box when user closed any dialog boxes.
The above implementation naturally suits the MVVM pattern as developers can easily handle UI operations that don’t involve the view model in the view layer itself. This way, we can maintain the view model to be completely separated from the view.
A noteworthy point on the routed event implementation in ClientUI is that it does not only completely implement the routed event framework such as the EventManager and the class-level handler, but also implement the RoutedEvent to the entire set of UI controls. This allows you to use the EventManager to handle the UI events from anywhere in your class – either in static constructor for class handler, or instance constructor for instance handler.
Streamlined View-ViewModel Abstraction
As the MVVM principles require the view model to be separated from the view, accessing the view (UI) elements from your view model become more difficult since you can’t directly reference to the UI instances in your logic. This separation concern has been one of the most difficult challenges in the MVVM implementation and eventually requires UI controls to be designed in a way that allows its members to be easily described from the view model through data binding.
That said, how do you suppose to set focus to a textbox if you don’t have a direct access to the textbox element? Or another example, how do you execute a command button when the enter key is pressed when the button references and key events don’t exist? As you’re exploring more into MVVM pattern, you’ll find more cases like these in other common UI operations.
The good news is that we’ve streamlined the View-ViewModel abstraction in our entire ClientUI controls, so that you can work with the controls intuitively in your MVVM project.
To respond the first question above, most of the logical containers in ClientUI family – such as UXPage, UXWindow, UXDialogBox and other container variants – introduced DefaultFocus property which can be easily bound to other element through declarative element binding in the view layer. As such, this eliminates the needs to write extra codes in either the code-behind or the view model of the corresponding view. See the image below.
The IsDefault implementation in ClientUI’s button family addressed the second MVVM challenge above. As user pressed the enter key on any valid input controls such as textbox, combobox or other input controls, the button with IsDefault enabled will be automatically discovered and executed. It’s nearly impossible to achieve this kind of design without a solid architecture that puts together logical and keyboard focus, focus scope, and routed event implementation. More interesting stuff on focus in the latter section.
Similar to the cases above, many of the common UI operations have been identified and streamlined throughout the entire ClientUI components – making it easier and simpler for developers to build MVVM pattern application.
DialogBox and MVVM
Like every common LoB application, we would like our users to be able to edit their contacts, add, or delete a contact. Our next task is to display a dialog box that prefilled with the user’s information. Users would then be able to edit those information and click the Save button to keep the changes.
Displaying a dialog box may sound fairly simple and easy at a glance, especially our ClientUI already includes full-featured windowing UIs such as window and dialog box. However, due to the MVVM principles, again we’re facing the condition where our view model codes should not directly access the view (UI) element.
Showing a dialog box, or a separate logical container that instantiated dynamically at runtime based on the view model logic, requires a special handling in a MVVM application. Several well-known approaches include using a mediator such as service provider or service locator pattern. However, since the service provider or locator are mostly in the form of architectural pattern such as interfaces and abstract classes, developers are required to write their own codes to glue their view (UI) elements to the service pattern. There are even more works to be done if the UI elements aren’t designed for MVVM semantics, which require developers to write another model interface for that particular UI elements.
All ClientUI-family components are built from the ground-up to fully support MVVM pattern by providing ready-to-use interfaces which are also implemented in our logical containers. This architecture also provisions the use of dependency injection, the pattern that we used in our SAF (Silverlight Application Framework) to load external modules and include the ability to inject them into the logical containers implemented in ClientUI. This topic will be further discussed in my next post.
Since our ClientUI already includes a full-featured shell architecture, we’re going to use service provider pattern to show our editing dialog box. The code is pretty simple and straightforward – no extra interfaces or abstraction needed. See below.
Pretty much self-describing, the above codes show how we can instantiate our editing dialogbox without directly referencing to its type. Notice that our dialogbox (UXDialogBox) is first converted to IModalWindow interface in the DialogBoxProvider.cs which is possible because the UXDialogBox implements the IModalWindow interface and thus complies to the contract required by the view model.
The following screenshot shows our Contacts application with the editing dialog box opened.
Notice that all input fields such as textbox and the dropdown will be automatically prefilled based on the assigned data context. In a properly written MVVM application, you’ll get everything to work flawlessly – automatically. That includes the data update and automatic propagation to the selection status and other UI that bound to the entity.
The UXDialogBox and the rest of logical container UIs also include several useful features that aids MVVM application development. For instance, UXDialogBox includes six predefined dialog results similar to those in WinForm which makes it much simpler to work with dialog box specifically in many common scenarios where the dialog result is often a unique value other than boolean.
Naturally, the button family in ClientUI – such as UXButton, UXDropdownButton, UXToolbarButton, UXStackButton and others– also implements the dialog result property. When the button is hosted in a logical container that implements dialog result, the dialog result value of the pressed button will be automatically recognized by the container and further processed according to the default behavior of the dialog result.
In this case, the buttons and dialog boxes and the rest of logical containers works in harmony to deliver intuitive development experiences, which ultimately gives significant advantages to MVVM pattern development.
It’s noteworthy to point out that this behavior also complies with the dialog box (logical container) requirements in WPF, which stated that setting the DialogResult property also causes the window to close automatically, which alleviates the need to explicitly call Close.
As such, executing the save button in our edit dialog box scenario above will result in the dialog box being closed automatically since its DialogResult property is set to a valid value. This alleviates the need to write codes in the code behind of the view and maintains the view model clean and completely separated from the view.
MessageBox and MVVM
Similar to the technique that we used to show the editing dialog box above, we can also show a message box using identical service provider pattern.
As we designed our ClientUI to have its own windowing and messaging system that managed through core shell (UXShell), it’s possible for us to create a better message box that blends nicely with our application’s look and feel. As such, instead of using Silverlight’s default message box that borrowed from the browser, we would like to show a more user-friendly confirmation box when users click on the Delete button in the toolbar, or when Ctrl + Shift + X is pressed.
Luckily, our UXMessageBox is already implemented as a static constructor and thus allows the message box to be instantiated anywhere in the view model. However, since we want our view model to be completely platform agnostic, we still need to create a mediator for the message box.
The implementation code and the result can be seen below.
Unlike in WPF that uses different result type for dialog box and message box, our UXMessageBox and UXDialogBox share the identical dialog result semantic allowing you to work with these controls in more consistent manner.
Watch the MVVM Contacts Sample In Action
Although I’ve included many screenshots and illustrations to accompany my writing, they are simply still images which don’t demonstrate the “feel” factor of our Contacts application. Therefore, here’s our Contacts application in Youtube video. Enjoy!
Please note that you may notice several interesting capabilities in the above demo which I purposely didn’t mention in this post. I planned to discuss them together in a one-off UI/X blog post and cover everything about user experiences in the ClientUI suite.
ClientUI, as far as it stands, has successfully met its key vision to deliver an end-to-end solution for Silverlight development that spans from architecture to UI layer enabling developers to rapidly build immersive line-of-business Silverlight applications using the pattern they preferred most – either the ViewModel or the Model-View-ViewModel pattern. With all that ClientUI has to offer, we hope that developers find building Silverlight solutions to be so much easier and enjoyable with less codes and issues, and also enables them to focus on the business logic and rich presentation that matter to them and their clients.
MVVM itself is a very broad subject and it’s certainly not feasible for me to discuss all aspects of it in a single post. However, hopefully this post gives you a good starting point to explore MVVM pattern in your next Silverlight project.
As we’re wrapping up the final feature sets for the ClientUI 2010 release, hopefully you can get a hand of the final bits in the next couple weeks. Private beta program is also available for selected customers, industry partners and Silverlight enthusiasts. The beta will include sufficient samples and materials that you can use to start building prototypes and testing the complete controls and features in your favorite IDEs. So, if you would like to participate in our private beta, please leave me a message with your name and email address and I’ll get back to you shortly with the beta bits.
In my next post, I’ll discuss about the user experiences part of the ClientUI components and possibly include couple of live demos that you can try online. Stay tuned.
All the best,
Chief Software & UX Architect.