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.

WPF assembly: XmlnsDefinition - identify types for XAML usage

by 20. June 2010 09:42

If a picture says a thousand words then the following should save me some typing as to the value of XmlnsDefinition (reference line 5 below) - it provides an easy to remember Url mapping to your namespaces. 

My PrototypeApp (born from the Prism DirectoryLookupModularity sample) has an Prototype.Interface project where much of the application specific code resides.   Within the AssemblyInfo.cs file (under the Properties folder) I was able to map all of the applicable namespaces to a single, easy to remember, url.

Excerpt from AssemblyInfo.cs follows: 

[assemblyAssemblyVersion("1.0.0.0")]
[assemblyAssemblyFileVersion("1.0.0.0")]
[assemblyXmlnsDefinition(http://www.Global-Webnet.com/PrototypeApp,
                            "PrototypeApp.Interface.Constants")]
[assemblyXmlnsDefinition(http://www.Global-Webnet.com/PrototypeApp
                           "PrototypeApp.Interface.ViewModels")]
[assemblyXmlnsDefinition(http://www.Global-Webnet.com/PrototypeApp,
                            "PrototypeApp.Interface.Controls")]
[assemblyXmlnsDefinition(http://www.Global-Webnet.com/PrototypeApp
                           "PrototypeApp.Interface.Converters")]

Demo source code follows: DirectoryLookupModularity.zip (5.82 mb)

Notice

Blog videos and references to CodePlex projects are no longer valid