Wednesday, 18 April 2012

Scoped Region Managers

I wanted to compose my manuscripts entry view within the job details view to give it some context. So, I added a region to my job details view and refactored my OpenView call so that it took a region name. This worked fine for the the first job, but broke the second time because the second job details view instance tried to register the same region name with the global region manager as the first one.

The solution to this is to use scoped region managers. When adding a view to a region using injected (rather than discovered) views, you can request that it creates a new RegionManager that you can pass to the ViewModel to use when creating the nested view. Here are some articles about this approach:

http://msdn.microsoft.com/en-us/library/ff921098%28v=pandp.40%29.aspx

http://stackoverflow.com/questions/6582612/prism-4-locally-scoped-regionmanager

Tuesday, 17 April 2012

ViewModel level acceptance testing

In the past, when writing acceptance tests for a project, I've usually used a GUI automation tool such as White (for desktop) or Selenium RC (for web apps). For this project I wanted to try something a bit different. I wanted take full advantage of the fact that I'm using the M-V-VM pattern and start acceptance test cases from the ViewModel rather than the View.

So instead of the tests firing up an instance of the compiled app, I've created an acceptance test bootstrapper that creates all the unity mappings that the application bootstrapper does, but replacing the mappings for UI related resources with RhinoMocks mock objects. This bootstrapper is called by the SpecFlow test framework before the tests start. This means that I can run virtually end-to-end tests on the application without any screen/keyboard/mouse interaction. This sort of test suite is ideally suited to being run on a build machine.

Another difference to the automation approach was that I change the way the database was initialised when the tests start. Usually the database will be dropped and rebuilt each time the model changes. For the acceptance testing, the database is re-created on each run. This provides a consistent data environment for the test to run in. To get this to work, I needed to set up a separate NUnit project that reloaded the test assembly for each run. This ensured that the Unity container would be re-created and the DBContext object singleton would initialise the database.

Monday, 16 April 2012

Testing the ViewOpener

I've added a new class and interface to the shell to allow modules to create views that cannot be reached from the menu. An example of this is the job details view which will be opened after adding a job and later on, from one of the job search screens.

I was running into a problem when testing this class that the tests needed to be run in an STA thread (Single Thread Apartment) as opposed to a MTA (Multi Threaded Apartment). This was because I needed to mock the views down to FrameworkElement level so I could access the DataContext property. As FrameworkElement requires to run in STA, I had to ensure that my tests run in STA. Here's an article I found on how this is down using NUnit 2.5 or higher.

http://madcoderspeak.blogspot.co.uk/2008/12/getting-nunit-to-go-all-sta.html

Friday, 13 April 2012

MVVM Validation

OK, I think I've finally broken the back of implementing the validation for the new job entry view. The first problem was that there was 2 types of validation going on. Firstly, there was binding error validation (for example, when I was binding from a text box to the budget (double) model property and I typed in some characters). The second type was the validation rules that I had added to my model through the IDataErrorInfo interface. I needed a way for my CanExecute evaluation method to pick up both types of validation.

I found a very useful article that did just this. I needed to introduce some base class logic for my View and ModelView:

http://karlshifflett.wordpress.com/mvvm/input-validation-ui-exceptions-model-validation-errors/

This solution had the added benefit that it made the binding exception errors more readable to the user when viewing them through the tool tip.

To get the validation solution to work, I needed to do several things:
  1. Make all my bindings TwoWay rather than OneWayToSource.
  2. Make all of my ModelView properties call NotifyPropertyChange, when set.
  3. Turn NotifyOnValidationError, ValidatesOnDataError and ValidatesOnException on on all my bindings.
  4. Use a RelayCommand instead of a DelegateCommand.
  5. I needed to change the type of the view from UserControl to BaseView.
This last change meant that I needed to be able to specify the generic type in XAML as well as the partial class. I found and article that explained how to do this:

http://www.codeproject.com/Articles/37317/Generic-Support-In-XAML

Next up is to start working on adding manuscripts to a job. Firstly I want the new job screen to close on successful save and a new screen open that shows the job title, number, contact name and process icons and provide a way to add the new manuscripts.

Thursday, 12 April 2012

Binding radio buttons to Enums

Found a good article that had the solution to binding radio buttons to Enums and not breaking the validation:

http://stackoverflow.com/questions/397556/how-to-bind-radiobuttons-to-an-enum

Also found another article about Enum Bit Flags which I might use to refactor the process flags on the new job screen.

http://msdn.microsoft.com/en-us/library/cc138362.aspx

I need to do some further reading to work out how to integrate the IDataErrorInfo calls with the CanExecute delegate. My initial investigations came up fruitless.

Wednesday, 11 April 2012

EF 4.1 doesn't support emums!

Whist building out the application with the job status and budget type found out that EF 4.1 doesn't support enum property mapping to database field. The properties just get ignored. To get around this, I had to add integer properties and wrap these in my enum properties.

Started having a look at the validation for the new job entry. I've been using IDataErrorInfo on the ViewModel to validate and report errors. This shows up on the screen as a red border around the control. I still need to find out how the mouse-over hint shows the error text. I also need to find out how I can integrate validation with the drag and drop functions. Because the user isn't entering data directly into the control, the same binding technique cannot be used.

Monday, 9 April 2012

Smart Search & Drag and Drop

Smart Search

One of the requirements is to be able to find existing contacts in the system and add them to a new job. I created a smart search where I could type a few characters of a name and it would list matches. I could then drag a matching contact over to the new job and insert it into the contact placeholder. This was simple enough, but I did run into a problem where the entity framework was creating new contact records rather than linking to the existing ones. This was because I was using separate EF context objects for the contacts and the jobs. So, when I save the new job, the context object had not recognised the contact as one that was already in the system. I fixed this by creating a factory method that returned a singleton instance of the EF context that both the contact and job data access classes could use.

Drag and Drop

To perform the drag and drop from the smart search to the new job view, I used some drag and drop code that I had used in the Prediction League application. I realised that if I was to use drag and drop extensively, I'd be copy and pasting this code into multiple views. What I really needed was to extract and generalise the code so that I could plug the drag and drop strategies in where needed. I managed to do this and learned a bit about using generics at the same time.

I'm going to look into a WPF drag/drop library on Google Code that uses attached properties to that the drag drop code can be written in the ViewModel rather than the view code behind.

http://code.google.com/p/gong-wpf-dragdrop/

Saturday, 7 April 2012

Oyrhynchus

Manuscript Tracking System is a rather uninspiring name for an application so I came up with Oxyrhynchus. Oxyrhynchus is a city in Egypt where they found a shed-load of ancient manuscripts. It sounds sort of weird as well, so I've borrowed it.

Technologies:

I'm using Prism 4.1 and the built in unity bootstrapper along with WPF 4. I'm intending to use SpecFlow for BDD and NUnit and RhinoMocks for the TTD. I'll be using Entity Framework Code First for the database layer.

UI Design:

I've designed a shell layout that has a menu on the left hand side, a main work area in the middle that is contained in a tab control. On the right side, I will have a smart search facility which will feature drag and drop of found items into the main area. The modules will register menu items with the shell, and the shell will manage the opening and closing of these views.