Architecting Silverlight LOB applications (Part 6) – Building an MVVM Framework

Hello again! In this post I’m going to talk about building an MVVM framework.

As I said in the previous post, this post should be about the OrderView. This view should allow users to pick items from a list of products, add them to the actual order, choose quantities, view the current total price and submit the order. Also the user should be able to filter, sort and do pagination on the product list. I’m sure you’ve seen enough blog posts from other people talking about this subject, that is getting the selected product, add it to another collection or create an order detail based on it, then update some other data on the UI and finally submit the changes back to the server. The thing is, everyone has its own way for programming and eventually when you end up in a team, you may find that two people coded the same thing in a different way, and one has a bug in situation A and the other has a bug in situation B. Having a good MVVM framework with a well defined methodology is a must to prevent these situations. In this post I want to talk about essential components you must have in an MVVM framework. Later, I’ll describe an MVVM Framework I’ve been working on which was based on WCF RIA Services but doesn’t really depend on it.

Since we’re following best practices, we know that using a good MVVM architecture we can come up with a solution whose fetching, filtering, sorting, paging logic is entirely separated from the view, allowing us to also have different views for the same view model. For example, we can start by using a DataGrid and a DataPager to display our items but later provide a new view that uses comboboxes to select the sort options, an album-like listbox to show the items and custom buttons for paging. Also, we should be able to separate all this logic from its actual data access logic to be able to use mock objects for our model and do unit tests for our viewmodels. That’s not an easy task but that’s what I want to achieve from now on.

Well, to start, .NET / Silverlight already offers us some classes and interfaces that are very handy for MVVM scenarios.

  • INotifyPropertyChanged – Used to raise an event when a property changes. WPF / Silverlight Binding framework use this interface to update the view when a property changes.
  • INotifyCollectionChanged – Used to raise an event when an insert, remove, clear or replace operation has been done against a collection. WPF / Silverlight controls that have an ItemsSource property usually use this interface to create or delete visual items in a container. For example, ListBoxes display new ListBoxItems, DataGrids display new DataGridRows.
  • ICollectionView – Used to provide filter, sort descriptions, group descriptions, and item selection for an IEnumerable collection and have the view display only the filtered items, sorted according to the sort descriptions and highlight the selected item. (Has more features but these are the most relevant for the sake of this post).
  • IPagedCollectionView – Used to provide paging options to an IEnumerable collection. This is used by DataPagers mostly, that make calls to the MoveToPage(int pageIndex) method and allows us to register in the PageChanging event and fetch a new page of entities to be displayed.
  • There are other important interfaces like IEditableObject, IEditableCollectionView but I’m not going to cover those in this posts. They are used to update property values of an object in an atomic fashion.

Continue reading

Architecting Silverlight LOB applications (Part 4) – Metadata and localization

Specifying metadata for our entities is the easy part and here is a good place to start localizing our app.

First what we have to do is create a buddy class as described in the following example:

[MetadataType(typeof(Customer.CustomerMetadata))]
public partial class Customer
{
    internal class CustomerMetadata
    {
        [Display(ResourceType = typeof(Metadata), Name = "MyApp_Customer_Number")]
        public int Number;

        [Display(ResourceType = typeof(Metadata), Name = "CommonProperties_Email")]
        public string Email;

        [Include]
        public EntityCollection<Order> Orders;
    }
}
[MetadataType(typeof(Employee.EmployeeMetadata))]
public partial class Employee
{
    internal class EmployeeMetadata
    {
        [Display(ResourceType = typeof(Metadata), Name = "CommonProperties_Name")]
        [StringLength(128, ErrorMessageResourceType = typeof(Metadata), ErrorMessageResourceName = "CommonErrors_StringLength")]
        public string Name;

        [Display(ResourceType = typeof(Metadata), Name = "CommonProperties_Email")]
        public string Email;

        [Include]
        public Department Department;
    }
}

The DisplayAttribute attribute is very useful, as it annotates your properties with information that can be consumed in various ways. For example, when using your entity in a Datagrid, the cell headers will automatically look up for DisplayAttributes and retrieve the localized string for that property. The same applies for labels in a Dataform and if you want to create your own UI framework, you can leverage this type of annotation to start localizing your app. Notice how I’ve reused some resource names for common properties like Email. The same could have been done for Number and Name, but that really depends on each case.

You can place validation rules on your properties as well using attributes like StringLength, apply regular expressions or even create your own custom validation rules. The great part about this is that those rules will be available in the client as well. The DomainService makes sure that before executing operations on entities all the validation rules are applied. Note that you can’t do all kinds of validation on your entities using metadata. Some validations may require connecting to a database, transactions, etc, and such information isn’t available in this type of validation context. I recommend that such validations are performed after DomainService’s ExecuteChangeSet is invoked and right before the PersistChangeSet method.

More on metadata specification can be found in the documentation or other resources on the web. I just want to focus on a different aspect that not many people tend to write about. That is sharing the Resources in the client and the server. The client project will not compile if the ResourceManager Metadata isn’t available. Since it is defined on the server, you should follow these steps in order to enable it on the client:

  • Add the resource files as a link to the client project
  • Change your client project’s default namespace to the same namespace that is defined in the server project that holds the resource files
  • Change the client project’s .csproj where it references the linked Designer.cs file and add these lines of code:

      <Compile Include=”..\..\..\Server\Data\MyApp.Data\Resources\Metadata.Designer.cs”>

            <AutoGen>True</AutoGen>      <Link>Resources\Metadata.Designer.cs</Link>

            <DesignTime>True</DesignTime>

            <DependentUpon>Metadata.resx</DependentUpon>

      </Compile>

  • Make sure the resource files have the same relative path in the client project as in the server project. In this case, I’ve created a Resources folder in both projects.
  • Also make sure that the resource file has Public marked as its Access Modifier.

These steps are necessary because adding linked files for dependent files, like Medatata.resx / Metadata.Designer.cs won’t automatically mark them as dependent, so you need to do it manually.

Now you should be able to compile your application and start taking advantage of metadata in your entities.

To finish, I’d like to say that all the code is available at http://code.google.com/p/mfelicio-wordpress under trunk/2010/SL-MVVM-RIA. I’m sorry for the delay on this one.

Next posts will be covering client development.

 

Architecting Silverlight LOB applications (Part 3) – DomainServices and Repository

Hello again,

In the previous post I described an overview of an architecture that could be used when developing silverlight modular apps. In this post I’ll start with a simple business domain model and create a domain layer around that model.

In this example our app will be a web application for a company that sells products and that can be used by its customers to fulfill orders and its employees to process them. These orders have details which consist of products and quantities. Each product can have a product category. When a customer submits an order fulfillment, an employee of the company may process that order to prepare the items for shipping.

The company has a few departments, and each employee belongs to a department. This means that employees from the Sales department will be to process orders; employees from the Human Resources department will be able to recruit new employees; and employees from the Financial Department will be able to watch some charts and print reports with statistics of how sales are evolving as time goes by, sales reports, etc.

Continue reading