TreeMap control primer with WPF MVP-VM

by 21. August 2011 09:34

Source: Treemap.zip (2.68 mb)

Note: the sample application uses a Portable Class Library (a library that can be used by WPF, Silverlight, Phone and XBox projects).  Resharper has not been updated to support these libraries so it will underline code in red indicating that it cannot find the applicable module - disregard these visual indications as they are false.

I learned how to use the TreeMap control from Diptimaya Patra's blog "Tree Map Control In Silverlight 3".   You may recognize the results as I used his data structures to complete the application I created to learn how to interact with the TreeMap.

My objective was to generate the TreeMap data from a reusable data structure (so the infrastructure could be easily used by other Presenters/processes).   Since REST services are the popular data sources these days I provide mock data from my data access layer using the following structure:

With the Model-View-Presenter, View-Model (MVP-VM) pattern the Presenter is responsible for instantiating the View (line 22 below), configuring the data context, and wiring up events.   In this case the App.xaml instantiates our Presenter and will Show() the shell that it is returned by Initialize().

With MVP-VM no business logic is in our View, the only code it will have is to raise events so that the Presenter can subscribe to them (line 25 above); this permits the View to remain reusable in other modules.   The DriveView (MainWindow class) is shown below:

If a TreeMap block is clicked on (right or left mouse buttons) or hovered over with the mouse the HandleConcreteTreeMapEvent (instantiated on line 46 of the Presenter above) will handle the request.  This method on the Presenter is called by the baseclass ViewEvent process which uses a factory to determine what ConcreteEvent to pass in to HandleConcreteTreeMapEvent.

The DriveTreeMapEventHandler (on line 49 of the Presenter above) contains the logic that will update the ViewModel - it follows:

We'll want to extend the TreeMapViewModel (baseclass) at some point so we'll derive DriveViewModel from it, however for now its existing functionality is all we need to get our TreeMap bootstrapped so it is currently empty.

The important thing to note in this application is that the View and ViewModel are loosely coupled, they could easily be reused in other application.   

PRISM V4 Drop 2 : MVPVM Modularity with MEF

by 26. June 2010 15:35

Sample Application: ModularityWithMef.zip (4.95 mb)

Although I have been a hard-core Unity (Dependency Injection) cronie since its conception I have to admit I was very pleased with MEF extensions to PRISM.  However, it did force me to rethink some design strategies that I've used since the Smart Client Software Factory - such as using generics to quickly wire-up base classes (you can't use generics with attributes).

Somewhat reluctant at first I scraped my earlier prototype/design and moved forward with a new design that is centered around MEF and PRISM V4 Drop 2.   I'll have to build an infrastructure that will minimize refactoring when PRISM V4 is released; particularly since PRISM, MEF and Unity will serve as the main tools.

The sample that is provided in the PRISM V4 Drop 2 looks as follows with the exception of the View on the right.  I added a new new "Hello World" view utilizing the MVPVM pattern; I use PRISM/MEF to wire-up the infrastructure.  

Note: Module F Imports two Business Logic Layers (DoctorBLL/PatientBLL) which in turn Import their respective Data Access Layers.  It then uses these, within its presenter, to populate the view model properties that the two ComboxBoxes are bound to. 

The end result after refactoring the sample is as follows:

  • The Model instantiates the Presenter 
  • The Presenter instantiates the View and wires up the view model as applicable

After wire-up the Presenter handles all business logic (you'll find no code in the code-behind files).   Below is all of the code required to wire-up the module A view with A)dd, E)dit, D)elete and P)rint buttons.   Modules A and E both use the same CRUDControl and each have their own CRUD View Models (derived from CRUDViewModelBase) which permit base functionality to be overridden, i.e., notice that Module E does not have a P)rint button.   The only wire-up required for the CRUDControl is shown on line 23 below where the DoctoCRUDViewModel.ParentViewModel is set with a reference.

The only issue I ran into, which will result in a message in the user forum is I couldn't figure out how to [Import] parts in the Bootstrapper - so currently there is some code in the MainWindow code-behind but as soon as I work this out I'll move what little code remains there into the Presenter.

Sample Application: ModularityWithMef.zip (4.95 mb)

Tags:

MEF | MVPVM | Prototype

PRISM 2.2: can't use StaticResource when resource is in App.xaml

by 22. June 2010 20:09

I lost count of the number of variations of "can't use StaticResource" that I BING'd for over the last couple of days; countless hours banging my head against the desk.

This adventure started when I created a prototype from the DirectoryLookupModule sample from the Prism 2.2 package (ref this prototype link).  As you can see from the link it went through a major transformation and it wasn't until the MVPVM infrastructure was in place (with Business and Data access layers consuming a simple service) that I started to implement a DataTemplate.

The problem was I couldn't access my DataTemplate from the merge dictionary entry for App.xaml UNLESS I made it a DynamicResource.  Where this worked just fine the pit-bull side of me had to know why....

It wasn't until the second day that I noticed that "all" of the resources in this sample application were using DynamicResource, it was this revelation that started the road to discovery.   At the end of the road was the following obsure little declaration in the constructor.   The Prism bootstrapper was being loaded during the constructor versus OnStartup!  This little oversite prevents the StaticResource from being usable in the Shell or any of its Modules.

The happy ending on this story was that while updating the Prism forum with this tidbit (it was where I started my journey to discover the cause of this odd-ball bug) I noticed that Prism 4 had a Drop 2 so  naturally  I downloaded it and at first was somewhat dismayed that Unity was no where in the picture but was shortly taken aback by MEFs angle at the problem; it was very cool to say the least and I am now in the process of moving my MVPVM prototype to Prism 4.

 

MVPVM: Sharing a CRUD control with multiple views

by 20. June 2010 13:45

The object is to reuse CRUD logic, such as enabling/disabling buttons, setting IsEditing flags that XAML can bind to, etc, without polluting our view models.   For this we have a CRUDViewModelBase class that we derive from and set flags based on our needs - in the example below (right image) we set IsPrintVisible to false effectively hiding the Print button for the Patient (Module D in this prototype application DirectoryLookupModularity.zip (5.82 mb) ).

Note that the DoctorViewModel and PatientViewModel have overrides for each of the button clicks as well as a reference to it's parent view model and shared criteria view model.   The CRUD logic is completely decoupled and can be encapsulated within each view model for each concern; we have a clear separation of concerns (SOC).

Once we assign the PatientCRUDViewModel to Module D's View we can see below that the [P] button is not visible.   The default behavior is to have all buttons visible as shown for Module A

Since the Modules job (ModuleA.cs in image below) to load the Presenter, and the Views (DefaultViewA.xaml) have no code in their code-behinds, it is the Presenter's (DoctorPresenter.cs) responsibility to execute business logic as required.  Below we can see where the doctorCrudVm.ParentViewModel is provided a reference to its parent view. 

A single presenter / view can handle multiple CRUD requirements easily using the CRUDControl.

Note: Where a View can only have one view model, a view model can be shared across numerous views (reused).  In the case of our sample application the Shell and Modules B and C all share the CriteriaViewModel which is defined in the bootstapper as a singleton (the MVPVM framework represented in the sample link above easily supports this). 

It is the ability to reuse this domain object, across multiple views and modules, that dictates our project structure.  The PrototypeApp.Interface contains all the classes used by this application (ideally I would have the Business and Data layers in their own projects so they can be reused across multiple solutions but this is just a sample prototype).

A key point not to miss here is that you don't want to populate your view model domain objects with business logic that does not pertain to managing its view.

DirectoryLookupModularity.zip (4.91 mb)

MVPVM: Integration testing using the Presenter

by 20. June 2010 12:17

The MVPVM pattern lends itself to effective integration/unit testing.   Since their is no code in the code-behind and the Presenter processes all business logic against the ViewModel and View it is the best component to perform integration test against. 

In the following application (download from this link DirectoryLookupModularity.zip (5.82 mb)) there are three view models:

  1. CriteriaViewModel - utilized by views E, B and C
  2. DoctorViewModel - utilized by view A
  3. PatientViewModel - utilized by view D

The MVPVM framework used for the attached application consistently uses the following for bootstrapping modules:

The ModuleBase<TPresenter> (see below image) instantiates the specified Presenter, e.g., on line 14 below we identify the "DoctorPresenter" as the presenter.

The PresenterBase<TView, TViewModel> (see below image) specifies the View and it's ViewModel which in this case is DefaultViewA and DoctorViewModel respectively.  On line 23 we register the view (DefaultViewA) with the TopLeft region which was declared in the Shell's XAML.  The remaining logic is the code required to wire-up a CRUD control and to get the current module load counter value so that we can see that the module dependency attributes are working correctly.

These baseclasses do all of the wiring up so that we can focus on business rules; we don't spend a lot of time getting our module up and ready for the requirements at hand.

The integration test for Module A's presenter is shown below (lines 46-52); it verifies that the infrastructure properly wired up the View and ViewModel. 

Did you notice that on line 24 above we set the container to null and on the following line use the container.RegisterServices() method?   On the surface this may look odd but it lends itself to testing the Prism environment.

We use the same RegisterServices in our bootstrapper as we do in our integration/unit test - we do this to ensure our environments match for testing purposes.  To accomplish this we use a IUnityContainer Extension class (IUnityContainerExtension), the only time container will be null is during testing so we instantiate a MockBootstrapper (lines 25-27 below).   From that point on we have the same registrations to ensure our test will run without complaint.

MVPVM - Model View Presenter View Model

by 5. February 2010 23:13

"Those who cannot remember the past are condemned to repeat it."
   - George Santayana

See new blog on topic for additional information MVPVM, Dec 2010.  If you don't know the difference between MVC and MVP then you'll want to read this MVC, Dec 2010

If you have to put code in your WPF code-behind, for any reason, then you've run into a limitation of MVVM alone;  a limitation that will prevent reuse, prevent proper unit testing and cause code bloat.   This limitation was identified in the evolution of architectural patterns requiring the need to evolve to the Model View Presenter pattern (MVP).  

History would tell us that the evolution of architecture (because of smart controls, newer technologies and limitations of older architectures) evolved as follows: 

MVC (Model View Controller)
 -> PresentationModel aka ApplicationModel aka MVVM
     ->  MVP  (Model View Presenter)
           -> MVP Split into Supervising Controller and Passive View

Understanding that the PresentationModel and MVVM are synonymous, the question to ask yourself when deciding to use MVVM alone is "what were the limitations that inspired the birth of MVP via the Potel and Twisting the Triad papers?".   For our environment the answer  was simple - we need a presenter. 

----------------------------------------------------------------------------------------------------

Although the following equation is true there are subtle differences that warranted a new name for the reasons John Gossman notes.  We'll reference authoritative sources on the differences.

Presentation Model = Application Model = MVVM  

In John Gossman (founding father of MVVM) "PresentationModel and WPF" John writes:

  • "On naming, my opinion at this point is the the Model-View-ViewModel pattern is a WPF-specific version of the PresentationModel pattern.  PresentationModel is a lot easier to say and to write, and is more widely known...but for now I'm sticking to M-V-VM terminology in my own thinking in order to capture the WPF-ness and to avoid any interpretation conflicts."

In Martin Fowlers "Presentation Model", 2004 article he defines the Presentation Model as follows:

  • "Presentation Model pulls the state and behavior of the view out into a model class that is part of the presentation. The Presentation Model coordinates with the domain layer and provides an interface to the view that minimizes decision making in the view. The view either stores all its state in the Presentation Model or synchonizes its state with Presentation Model frequently

    Presentation Model may interact with several domain objects, but Presentation Model is not a GUI friendly facade to a specific domain object. Instead it is easier to consider Presentation Model as an abstract of the view that is not dependent on a specific GUI framework. While several views can utilize the same Presentation Model, each view should require only one Presentation Model."

In Martin Fowlers "Gui Architectures", 2006 article he states the following about Application and Presentation Models:

  • "The main difference between using an application model and classic MVC is that we now have an intermediate class between the domain model class (Reader) and the widget - this is the application model class. The widgets don't access the domain objects directly - their model is the application model." - para below figure 9.
  • "Application models allow us to separate behavior and state that's particular to the UI from real domain logic." - 2nd para above Figure 11
  • "Directly updating the widgets like this is not part of Presentation Model, which is why the visual works application model isn't truly a Presentation Model. This need to manipulate the widgets directly was seen by many as a bit of dirty work-around and helped develop the Model-View-Presenter approach".  - para below figure 11.

----------------------------------------------------------------------------------------------------

So why a new name - MVPVM?

"to avoid any interpretation conflicts" - John Gossman

Why is MVPVM necessary?

Short version - for reusability and to have a clear separation of concerns.  

Longer version - For all the reasons we evolved to both MVP and MVVM; they are still valid and the same problems are still being solved.  The only difference is that neither can solve the problem alone "easily".

What is the problem being solved?

We are using MEF/PRISM/Unity for the dependency injection of reusable components.  We may have a need to update the widget (view) directly depending on the complexity of the requirement (will one line of code remove the need for complex bindings); we want an extensible framework that will provide us the option.  Let's use the following Visual Studio 2010 use case diagram as the basis of this discussion.

 

Reusable component:  Person View; it is a UserControl that is resolved (instantiated) by the applicable presenter (its relation to the presenters are not shown in diagram to reduce complexity) 

Business rules:  Only the Admin Staff can view the Social Security Number field of the Person View. 

Assumption: There will be numerous business rules that will affect the behavior of the view.

THE PROBLEM / SOLUTION SCENARIO

We're starting our sprint and I'm handed the "Add Patient" requirement.  It has a business rule that states only Admin Staff can have access to the SSN field.  The user wants a list of patients sorted by last name so that they can verify that the patient in question is not already in the system.  This list should be tied to a lookup field that will locate records in the list as the user types the letters of the name.

I would start by grabbing the available reusable views, user controls created by designer(s), to compose my main screen with.  In our example we'll focus solely on the "Person View".   From the use case diagram I can see that this view has a "Person View model" that it binds to with a provision for the SSN Visibility rule; the Person View will reflect the state of this behavior {collapsed, hidden, visible} effectively showing/hiding the SSN field based on its settings.

Problem:  I can see by the high level use case that I won't be the only presenter that implements this view (and view model).  I can't pollute the ViewModel with any business logic or data access logic.

Solution:  Have my presenter retrieve Patient Records (where personType=Patient) and use it to populate a ListBox.  The presenter will subscribe to the selected index change event of this ListBox via the EventAggregator and when the presenter is notified that a user has changed a patient it will update the PersonViewModel fields as applicable.   The presenter will set the SSNVisibility property to "Visible" and our job with the PersonView and it's view model is done.  

Could a switch statement for visibility be placed on the PatientViewModel?  Yes and it will also have to know who the actor (parent) is that is consuming it.   Can it retrieve the user record?  Yes and it would require knowledge of the patient's primary key.   Will every process require data access to get the record?   Probably not - the information could reside in another control.  

In our environment we want to remain loosely coupled to minimize, if not remove, any impact on other users of a view (and its view model).

 

Notice

Blog videos and references to CodePlex projects are no longer valid