M-V-VM Building an ERP-system – part 3 of N – the first ViewModels

Skrevet - Friday, May 28th, 2010 kl. 23:26 | Kategori - * Coding, English posts

After part 2 – we now have a model to work from – and it is time to create the first ViewModel.

After some carefull consideration – I’ve chosen that we need a list of Customers where we can perform CRUD (Create, Read, Update, Delete), to make things a bit interesting, we want to have a paged view as we expect our customers to range in the thousands – so we have the basis for our first ViewModels interface (and a few helpers):

public interface ICustomersViewModel:IPagedViewModel<ICustomer>
{

ICustomerFilter CustomerFilter {get;}
ICustomerCommands CustomerCommands {get;}

}
public interface IPagedViewModel<TEntity>:INotifyPropertyChanged
{

IEnumerable<TEntity> PagedData {get;}
ICommand MoveFirst {get;}
ICommand MoveLast {get;}
ICommand MoveNext {get;}
ICommand MovePrevious {get;}
int CurrentPage {get; set;}
int PageSize {get;set;}
int NumberOfPages {get;}

}
public interface ICustomerFilter:IBaseFilter
{

string AccountNumberSearch {get;set;}
string CompanyNameSearch{get;set;}

}
public interface IBaseFilter:INotifyPropertyChanged
{

event Action FilterUpdated;

}
public interface ICustomerCommands
{

ICommand NewCustomer {get;}
ICommand EditCustomer {get;}
ICommand DeleteCustomer {get;}

}

It might seem a bit complex for a simple list, but remember this is the refactored version after several other ViewModels have been built, so DRY has been applied. A few notes:

Why a separate class for the Commands – and why don’t you use the ApplicationCommands?
To keep the code straightforward and keep responsibilities apart (SRP), I try to keep the Commands seperate from the logic driving the querying. The reason, I don’t use ApplicationCommands is that in .Net 4.0 I get bindable InputBindings which will allow me to avoid code-behind routines to relay keyboard shortcuts – and ApplicationCommands will force me to do write new code-behind to wire them up to my commands. I would rather assign keyboard shortcuts than have messy code-behind.

What’s up with the Filter – why not publish just the string property in the viewModel?
A valid point – my experience is that Filters change as the customer gets to know the product – so I’d rather change a small filter class (plus the repository) without having to change the ViewModel class. Basically, I’m applying a change-rate dividing logic here – things that change often are isolated. Also, I want to make it clear what the search property is all about – it is easier to explain that all the properties in the filter-class are for reducing the query and everything in the ViewModel has something to do with interacting with the query-result (here changing pages and so on).

Why an extra event on the filter – it already has INotifyPropertyChanged?
I want to be explicit about when to update the data in the list. I might want it to update less times than properties change – or might delay it (for users with rapid keystrokes there is no sense in loading the list 6 times within one second). Also, if I end up with ranges – e.g. dates, I might update both dates and only want one update (e.g. when one date is entered that will result in an invalid date range – I will change the other date to produce a valid range).

Next, we need a detail view to edit the customers:

public interface ICustomerDetailViewModel:IEntityViewModel<ICustomer>
{

string AccountNumber{get;set;}
string CompanyName{get;set;}

}
public interface IEntityViewModel<TEntity>:INotifyPropertyChanged
{

ICommand CancelChanges { get; }
string[] ValidationErrors { get; }
ICommand SaveChanges { get; }
void SetActionOnClose(Action action);
void SetEntity(TEntity entity);

}

Not many surprises here – we need to be able to edit the customers details, as well as designate whether we want to commit changes.

What is the SetActionOnClose method about?
This is a hook to handle removing the view. Remember that the ViewModel has no knowledge of the View on top of it – and has no idea where it is placed, so we need a way to tell the ViewModel what to do when it is time to close.

In Part 4, I’ll look at implementing commands.

About the series:
The solutions introduced here are not entry-level material. You should understand generics and basic patterns to fully utilize the material presented. The solution represents about 3 years of experience working with one ERP-solution. Some of the choices taken are heavily influenced from the large-scale solution and may seem overkill for the simple examples here, but the idea is to show the end-result of my experience and hopefully you as the reader will at least see a new way of doing things. The solution is built in .Net 4.0 with heavy use of WPF’s capabilities. Here you can find the source-code for the series. You are free to use this code for any purpose, but it is presented as-is with no guarantees. Enjoy!

Feed | Trackback |

2 Comments
  1. Goblincave » M-V-VM Building an ERP-system – part 4 of N – commanding said,

    June 6, 2010 at 22:25

    [...] part 3, we are getting ready to tie things together and as many might know, WPF contains the really nice [...]

  2. Goblincave » M-V-VM Building an ERP-system – part 2 of N – the model implementation said,

    June 9, 2010 at 9:14

    [...] Part 3 will focus on the first ViewModels. [...]

Post a Comment