In this post i am going to talk about the most import part of the Silverlight and WPF applications, the View Model and the MVVM pattern.
UI development Challenges
View Models are designed to solve certain problems that pop during the UI designing.
- The major problem is that the User Interface code is difficult to test especially with automated tests. This is because the Code behind lives in the UI. Suppose we want to test a method in a code behind file like MainPage.xaml.cs then we have no other choice but to make an instance to the MainPage class, so when we do that the constructor is called will call InitializeComponent() and it will load all the xaml controls which will make the copy of the User Interface tree available and this a major problem in Unit Testing because some components might not work correctly till they are displayed as they make assumptions about the messaging and event handling. So the behavior of MainPage might be different from what it would have been at runtime.
- Another problem with code behind is that big and complex classes which are really difficult to maintain and are not flexible. You can easily get used to using the code behind for you code because that’s where Visual Studio adds the event handlers automatically. The best approach for coding is to have well defined classes with narrow responsibilities.
- The code behind job is to interact with the User Interface objects but when we start to add behaviors in the code behind which interact with User Interface objects we give our classes a wider scope and that’s the start of problems. It becomes all the more problematic when the application logic starts to integrate with the User Interface elements and the state of the application is saved with the help of user Interface elements.
- Another reason for the problem is overdoing the Data Binding. When you application logic starts depending on your Data Binding states. One example that comes to mind is that when the validation rules are made dependent on Data Binding which should actually always be the part of our application logic.
This is the technique which is recommended for overcoming the problems mentioned above. By using separated presentation we can avoid xaml codebehind by removing user interface manipulation logic in code behind, interaction logic in code behind, application logic in code behind and everything else not required in code behind. The best thing to do is to keep as less as code as possible in the xaml code behind. Keep any kind of application logic in a separate class which is generally named as Model. So we should make the model only concerned with the application which says what the application does and not how the user interacts with the application. Now UI class should not have any of the interaction logic because of the problems I described in the previous section so we need to create another class which will hold the interaction logic. This is the View Model. This governs any non-trivial logic. It will have the logic for the User Interface to behave the way we want it to behave.
Model View View Model
So let’s talk about each component.
- Model – A model is a classic model which comprises of the C# classes. It has not reference to the user interface and is not aware of the existence of any User Interface. The Model classes are compileable without any reference to the User Interface classes. The types in the Model consist of the concepts our application works with. If should be able to take these classes to any console application, web application or windows application and they should be able to compile with no problems. During the design of the Model we need to take decisions on how will the model be used? For example we situations where the Model is shared by both the client and the server or the model can mostly stay in the server or the model can completely stay in the client.
- View – View is generally a User Control. In Silverlight it is a good idea to split up the user interface into multiple User Controls.
- View Model – For each View we write a View Model. So the main purpose of the existence of a View Model is to serve the View. It’s possible for a particular view model to span into multiple classes. The bottom line is that the View model serves the purpose of presenting data or screen to your application. The reason it’s called a view model because adapts a particular model for the specific view. Like the model, the view model is a C# class and is not required to derive from a particular class. Sometimes it makes sense to make a base view model and derive from the same but the pattern does not demand that. But unlike Model it can use Silverlight types in its properties. The important things that define the View Model is that the information flows between View and ViewModel via Data Binding and this enables ViewModel to change the View without having to depend on the view. This is very useful for testability as we can instantiate the ViewModel without having to create the View. We can just use the View Model and invoke the methods and get the values back for testing.
Let’s see some code now.
- Create a new Silverlight application. And create 3 folders in the Solution Explorer named Model, Views and ViewModel.
- Let’s add a couple of classes in the Models folder. Add 2 new classes named UserModel and MessageModel to the Models folder and add the content as below.
- To increase the abstractions lets add a new folder in the solution named services and add an interface to it named IModelProvider and add the following code to it. This abstraction will make testing easier for us.
- Let’s add another class named ModelProvider.cs in the services folder which will be dummy data provider for this sample application. Add the following code to this class.
- The way we will handle user input in this application is via commands. .NET provides an interface named ICommand which gives us abilities on a User Action – Invoke and Enabled. ViewModels often provide commands through properties because it provides an option to connect the button to the view model without needing any code in the code behind. It is a good approach if you want a way to enable or disable the availability of command as anyways there will be a property exposed to the view by the view model. So it makes a lot sense to use one property to handle the enabling and invoking a command via one property. Silverlight does not implement icommand. Only button and Hyperlink are able to user ICommand but we need to implement it in our code. Let’s add a new class named RelayCommand inherting from ICommand. This will be the relay the action to the method of our choice. We can also refer this as a delegate command as we use a delegate a to specify the method to invoke. Let’s add the following code to the RelayCommand.
- In the Views folder let’s create new viewmodels. Create a new class named MessageItemViewModel.cs and add the following code to it. It’s the job of the view model to provide the data to be displayed. The all message view model will create one of these for each item in the page. So it will not only require a reference to the model provier but also the particular message which it will wrap. We will add three properties which will extract the MessageAuthor, Message Title, Message Body from the underline model object.
- Let’s add another ViewModel for all available messages name AllMessagesViewModel. The view model asks the provider for all the available messages and then wraps each one into the message item view model. So that the view can have an items control which can have a list of the items.
- Now let’s create the View for the ViewModels that we have created. Create a new UserControl named MessageItemView.xaml. let’s first add a reference to ViewModels
- Also set the reference of the DataContext to the MessageItemViewModel. The d: here represents that this data context is design time and will not be effective at runtime so we need specify that later as well.
- Now add the following code to the MessageItemView.xaml. This will contain the per message user interface.
- Let’s another View which will be the home for the View that we just created. Let’s name this view as AllMessagesView.xaml and add the following code in the xaml. This view just contains a ItemsControl inside scrollviewer and this items control just has a item template as the MessageItemView. It will create an item view for each message item.
- Also let’s add the following code in the code behind for this.
- Finally add the following code to your MainPage.xaml.
The code of this post is available here.
Any questions, comments or feedback is most welcome.