Using several ViewLocator.LocateForModelType?

Dec 2, 2010 at 2:44 PM

Sorry that the topic isn't more descriptive, but I really didn't manage to explain my problem in a few words. I'll try to explain my scenario:

I have an application with one root folder for each "feature", in this case FaultStores. This folder contains all the ViewModels and Views and a subdirectory "Model" that keeps classes specific to that feature. In this "Model" directory I have two POCO's wich I want to "attach" views for, "FaultStoreSummary" and "FailedMessage". The first one, FaultStoreSummary, worked like a charm. I created my class in the "Model" directory and then a view called "FaultStoreSummaryView" along with the rest of the views for this feature. I added the following code to the Bootstrapper:


ViewLocator.LocateForModelType = (modelType, displayLocation, context) =>
    return modelType.Equals(typeof(FaultStores.Model.FaultStoreSummary))
        ? new FaultStores.FaultStoreSummaryView()
        : locateView(modelType, displayLocation, context);

My ViewModel that uses this FaultStoreSummary has a property: 

public FaultStoreSummary FaultStoreSummary { get; set; }

and the View itself has a content control:

<ContentControl x:Name="FaultStoreSummary" />

No problems, this works. The problem is when I now wanted to add another View for my other POCO, called "FailedMessage". I did the same thing, I created a View for that class called "FailedMessageView" with the rest of the views for this feature and then added another ViewLocator.LocateForModelType... for this Model/View:

ViewLocator.LocateForModelType = (modelType, displayLocation, context) =>
    return modelType.Equals(typeof(FaultStores.Model.FailedMessage))
        ? new FaultStores.FailedMessageView()
        : locateView(modelType, displayLocation, context);

The ViewModel and View that uses "FailedMessage" now works, but now the FaultStoreSummary doesn't work! The error message is:

"...UserInterface.FaultStores..FaultStoreSummary not found".

If I, in my bootstrapper, change the order of the ViewLocator.LocateForModelType and puts the ViewLocator for my FaultSummary last, it starts to work but then the FailedMessage isn't found instead.

I've just copied the ViewLocator-bootstrapper-code from the GameLibrary-bootstrapper and assumed that this was the way to go if attaching several different views for POCO's, but now I'm starting to realise I don't get how the ViewLocator thingie works...

So, is there another way of "attaching" several views to several POCO's from the bootstrapper? I really like this approach and doesn't want to use xaml for this if I don't have to. 

Note: I'm not trying to use the SAME POCO for several views, just several "One View per POCO".


Thanks for a superb framework!




Dec 2, 2010 at 2:49 PM

Well, just after I posted I found what created the problem. I was using the same:


Func<Type, DependencyObject, object, UIElement> locateView = ViewLocator.LocateForModelType;


So instead I added one Func per ViewLocator.LocateForModelType i used:


Func<Type, DependencyObject, object, UIElement> locateFaultStoreSummaryView = ViewLocator.LocateForModelType;

Func<Type, DependencyObject, object, UIElement> locateFailedMessageView = ViewLocator.LocateForModelType;


This works, but I'm now curious if there's a more elegant way?


Dec 2, 2010 at 3:32 PM

LocateForModelType is just a function that the framework calls passing you in the VM it is looking up and expecting you to return a type of view that should be mapped to. We provide a default, simple implementation. You can replace this function with any logic you want, completely changing the system if you desire. In your case, I might consider creating a second set of conventions to map your model objects. Perhaps you can look for a different namespace pattern and map things differently? If you take a look at the GameLibrary sample, you'll see that it does just that for mapping a DTO to a view.