View/ViewModel Association - Convention and Configuration-based Approaches

An overview of both convention and configuration approaches to associating a view to its corresponding view model - the concepts and the concrete implementation available in Silverlight.FX. Also, to coincide with this blog post I updated the Silverlight.FX build to v3.4, which has a few additional features included as well.

Some time back, I blogged about different options to hook up a view to its view model when following the ViewModel (aka MVVM) pattern. There are multiple approaches in use out there. I raised the possibility of a convention-based approach in addition to existing ones like the ViewModelLocator pattern.

Motivation: I find the simplest way to explain ViewModel is to present it as a better code-behind, especially to the mainstream developer who is intimately familiar with the latter (at least in the .net world). With the code-behind approach the UI, its state and operations are all mixed up. The ViewModel pattern is of course designed to help separate application logic from the view, but now results in two discrete halves that need to be reconnected. Result: additional concept count. With a convention-based approach, I believe the simplicity of the code-behind model can be achieved while preserving the ability to decouple.

Like most other convention-based systems, it addresses the common and mainline scenarios well. There will always be some more advanced or less common scenarios that will fall out of the convention, for which a configuration-based approach needs to exist alongside.

With that context, I want to share what Silverlight.FX (@silverlightfx) now offers around hooking up a view to its view model by following a convention over configuration approach, to provide simplicity while retaining flexibility.


Convention

Silverlight.FX provides a convention-based approach, and after having using it for a while, it has worked for close to 100% of the scenarios I have personally encountered.

Quite simply the convention is for the view to look for a class in the same namespace/assembly with a type name formed by taking the view's type name and appending either a "Model" or "ViewModel" suffix.

I usually structure my view and associated view model as shown in the screenshot of the solution explorer and the convention matches that mental organization model. The snippets of code and markup below represent the typical content in each of those files:




MainView.xaml (XAML markup)
<fxui:View
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:fxui="clr-namespace:SilverlightFX.UserInterface;assembly=SilverlightFX"
  x:Class="MyApp.MainView">
  ...
</fxui:View>
MainView.xaml.cs (code-behind)
namespace MyApp {

    public class MainView : View {

        public MainView() {
            InitializeComponent();
        }
    }
}
MainView.Model.cs (view model)
namespace MyApp {

    public class MainViewModel : Model {
        /* properties, methods and events */
     }
}

So you might be wondering about <fxui:View>. The convention is implemented by the View base class. View is simply a UserControl with the smarts on locating a view model class, instantiating it (through an IoC container if one is present), and setting it up as the Model and DataContext for itself.

Note, that there are a couple of interesting derived classes deriving from View: Page which adds navigation semantics, and Form which adds dialog semantics that derive from View. All of these support the convention-based ViewModel association.

There are some cases where the above convention doesn't work. The scenario I've seen is where you have a view model that is shared by multiple views. This leads to needing a configuration-based approach.


Configuration via Attribute - Specifying View Model Type

The simplest way to specify the view model type using Silverlight.FX is to annotate the view with the [ViewModel] metadata attribute. The View base class shown above looks for this attribute before it tries to look for a type matching the above convention.

For example if I have a ViewModel such as CustomerViewModel that I want to share across a couple of forms, such as CustomerEditForm and CustomerInsertForm, I can do the following, without having to do anything in the XAML markup in those views:

// The views - forms to edit and insert customers
// (both associated with the same view model type)
[ViewModel(typeof(CustomerViewModel)]
public class CustomerEditForm : Form {
}

[ViewModel(typeof(CustomerViewModel)]
public class CustomerInsertForm : Form {
}

// View model that is shared by both forms above
public class CustomerViewModel : Model {
}

So far what we've seen is relying on the View base class and having it instantiate the view model type. There might be cases where you want to use a vanilla UserControl, or there might be cases where you want to take over the instantiation of the view model type yourself.


Configuration via Attached Property - Using a ViewModelLocator

Silverlight.FX provides a View.Model attached property. Using that allows you to associate the view model explicitly (to any UserControl, or View), as well as take on the responsibility of creating and initializing the view model.

For example, here is a UserControl with an explicitly set ViewModel:

<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:fxui="clr-namespace:SilverlightFX.UserInterface;assembly=SilverlightFX"
  fxui:View.Model="{Binding CustomerListModel, Source={StaticResource ViewModelLocator}}">
</UserControl>
Here's how I would define my ViewModelLocator class within my application:
namespace MyApp {

    public sealed class ViewModelLocator {

        public CustomerListModel CustomerListModel {
            get {
                /* create and return an instance of CustomerListModel */
            }
        }
    }
}
And finally, I would declare an instance of the ViewModelLocator in application resources, so that all views in the application can bind to it:
<Application
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:app="clr-namespace:MyApp">

  <Application.Resources>
    <app:ViewModelLocator x:Key="ViewModelLocator" />
  </Application.Resources>

</Application>

Notice that I bind View.Model, rather than DataContext as you might have seen in other ViewModelLocator demos. This has the effect of setting up View.Model, and setting DataContext as a side-effect. This allows the ability to lookup the model associated with the view anywhere within the view, even if the DataContext changes as you go deeper into the visual tree. For example, an item in an ItemsControl has a different DataContext, but shares the same view model, and is able to access it.


Design-time Experience

At design-time, designers like Blend and Cider need information about the type of the value assigned to the DataContext of a view, so various binding pickers and dialogs can understand the object model to display properties to bind to.

This can be accomplished using a design-time DataContext value. For example:

<fxui:View
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:fxui="clr-namespace:SilverlightFX.UserInterface;assembly=SilverlightFX"
  xmlns:app="clr-namespace:MyApp"
  x:Class="MyApp.MainView"
  d:DataContext="{d:DesignInstance Type=app:MainViewModel}">
  ...
</fxui:View>

Of course, I'd like the tools to also become aware of and support the convention, so that the design-time DataContext can be inferred without explicit assignment. I am working with Blend/Cider on this... it might be possible to implement support for this today using Cider's design surface extensibility - something to look at.


Summary

I personally find the convention approach quite compelling. I've in fact changed all the Silverlight.FX samples to use it. At the same time, I recognize a configuration approach is essential when you need it, and it can co-exist and step in when convention doesn't scale to the requirements at hand. However by default, the convention simplifies and cleans up things.

One of the reasons why I'm sharing Silverlight.FX, besides it being a fully usable application framework for your own applications, is to hear your thoughts on ideas such as this. So please do share your feedback, as I am working with the runtime and tools folks on additional view model support going forward.

This was implemented in Silverlight.FX since late last year, and now I've created and published an updated public build (version 3.4) of the framework along with sources (if you're interested in the behind-the-scenes details), and sample applications (to see this work in practice). Head over to the Silverlight.FX project page to download the latest release. This latest version contains a number of other controls and a few renames as well (as I start preparing for a Silverlight 4 version of the framework). All of these are features and changes are documented within the History.txt file when you download the zip.


On a side note, you can follow me, @nikhilk for quick updates and/or Silverlight.FX, @silverlightfx for updates/announcements via Twitter in addition to blog posts.

Posted on Friday, 2/26/2010 @ 10:47 AM | #Silverlight


Comments

17 comments have been posted.

Fredrik Normén

Posted on 2/26/2010 @ 11:04 AM
I use the same approach in a WPF app using Unity to Resolve my ViewModels instance.. my experiance of the convetion over configuraiton, is that I can simply add a View and then a ViewModel, no need to add any extra code..

ddilillo

Posted on 2/26/2010 @ 11:36 AM
nikhilk,

so far as convention based approaches go to view first dev i liking it. however, as a dev who does a lot of wpf based smart client work, i'm curious how (if at all) you would set up grid or list based edit scenarios where the list items themselves are viewmodels? would they simply not get a view? is this something that is taken care of through the locator? if they do get a view, how is it associated with the viewmodel if the viewmodel instance needs to be created by the parent viewmodel? like if you had an "Add New" command exposed by the that added a new child viewmodel to his children collection and relies on databinding to create the ui that constitutes its view.

disclaimer: i haven looked at your fx, so if its pretty well covered there in feel free to ignore my post, but i would appreciate your (or anybody else who would care to chime in) thoughts ...

Nikhil Kothari

Posted on 2/26/2010 @ 11:45 AM
@ddilillo
First, you can have view model first co-exist with view first. In fact Silverlight.FX supports this for modal form scenarios - the parent view model creates the child view model, and the parent view creates the child view, and hands it the child view model, rather than have the child view model create the view model on its own.

Second, the list item scenario - I think view models are models first and foremost - classes with properties, methods, events. As such the DataTemplate for the list item is the view, and its view model is the data item within a list. In this case there isn't a need to locate a view model type or create an instance of it, since the instances are already there and available by virtue of enumerating the collection that the list control is bound to. Hope that makes sense...

Btw, I do recommend checking out the framework :-)

Steve

Posted on 2/26/2010 @ 5:07 PM
I've been a mvvm fan but actually when I see all the hoops to jump through I wonder at times how
effective this is

Let's step back a moment and say that the two main reasons for this is testivility and dependency injection (ie service)

So at times I think the answer is more on better ways to utilizes and design these frameworks

ie. Why isn't Silverlight using traditional mvc pattern out of the box ?

I see no reason why not to just use event handlers in code behind because after using icommand and coding up all that logic to simply do a combos 'onselectedindexchanged' feels like 3 steps
back

code 'reuse' is highly overated so viewmodels are obviously not about reuse

I'd like to see more framework features like built in IOC containers to make wiring up dependencies more natural

Nikhil Kothari

Posted on 2/26/2010 @ 9:09 PM
@Steve
Why view model is an excellent question? I think it will turn into more than a comment, so stay tuned for a subsequent blog post, as I collect my thoughts. For now, I'll just say, I've found it to be indespensible (once you get comfortable with it).

MVC - I think MVC is super useful and interesting, esp. in the context of navigation... check out this past post of mine: http://www.nikhilk.net/Silverlight-ViewModel-MVC.aspx

ICommand - I pretty much never implement ICommand in my view model. Instead Silverlight.FX allows you to bind events to vanilla methods on your view model and pass in parameters from the view. Its very simple and straightforward in my opinion.

Code reuse - I might be an exception here, but I think view models aren't that reusable. Hence the common/mainline 1:1 mapping, and hence the convention I allude to in this post.

IoC - Silverlight.FX has a minimal IoC built in, and view models and MVC controllers are all created through the IoC container so they get their dependencies resolved automatically. You can almost use IoC without knowing much about IoC - If you download Silverlight.FX and browse the samples, you should see that - look for [Dependency] and [Service] and ApplicationContext.Components.

Matt

Posted on 2/26/2010 @ 11:12 PM
This is a very interesting post. I've been working quite a bit with PRISM in recent months, and the commanding infrastructure provided in PRISM require a decent amount of work to implement all of the commands one one need aside from button click commands.

Does Silverlight.FX have provision for modularity (i.e. dynamically loading assemblies on demand) as PRISM does?

Nikhil Kothari

Posted on 2/27/2010 @ 12:21 AM
@Matt
I will certainly recommend you check out how operations can be implemented in the view model and how controls can bind to them, without requiring implementing commands when using SilverlightFX. Example:
class MainViewModel {
public void Search() { ... }
public void Filter(object item) { ... }
}

<Button fxui:Interaction.ClickAction="$model.Search()" />

In other words, you don't have to implement commands, which I tend to think of as glue in the view, just like bindings, rather than things a view model should expose. Also, you can bind any event, and not just click. Click just happens to have a shortcut syntax. For those other events, you'd use the long syntax... example (which also shows passing parameter data):
<ComboBox>
<fxui:Interaction.Triggers>
<fxui:EventTrigger EventName="SelectionChanged" Action="$model.Search($element.SelectedItem)" />
</fxui:Interaction.Triggers>
</ComboBox>


As for modularity, the short answer is not yet. Its certainly a goal to bring some notion of modularity and composition support in Silverlight.FX.

John Kattenhorn

Posted on 2/27/2010 @ 6:53 AM
Hi Nikhil,

I really like the 'style' of your framework; not too heavy but very useful - having now played with a few different concepts and frameworks (and now have an application which is patchwork of both (I must refactor soon!). Could you us know if your currently release in source code could be built and compatible for SL4; i have a really pressing deadline which i'd like to use your framework on but it has to be with SL4.

Thanks

John

Nikhil Kothari

Posted on 2/27/2010 @ 8:31 AM
@John
Thanks.
I haven't tried it myself, but I believe you should be able to recompile the framework on SL4, because SL4 really is meant to be backwards compatible and an inplace update from a platform perspective. There would be a few changes I will make to better use what is new in SL4 when creating the SL4-specific version, but things should be usable before then. As for when I'll be looking at doing that, it will be post-MIX. If you hit something do let me know via my contact form.

Phil Cockfield

Posted on 2/27/2010 @ 12:14 PM
Hi @nikhil,
This is really interesting, thanks. I've been wanting to lower the ongoing tax of view-model hookup. I wonder if you could comment on this conundrum I'm having:

I typically have a graph of child view-models represented within a view-model. Eg:

- RootViewModel
|-- ChildViewModel [Property]

[ChildViewModel] is setup with state from the parent [RootViewModel] - and generally controlled by it. Within [RootViewModel]'s XAML there will be the element decalration for <ChildView> and it will bind to the 'ChildViewModel' property. Eg:

<RootView>
<ChildView DataContext="{Binding ChildViewModel}" />
</RootView>

====

What would you propose for this kind of situation? In this situation is there a trick I can pull, where the <ChildView> still creates it's view-model automatically and the [RootViewModel] somehow gets hold of it to control it? Or is this all wrong? Or perhaps this is fine and I should keep doing this???

What do you do in these cases, where the ViewModel requires speficic state and context information at construction?

Thanks Nikhil!!

Nikhil Kothari

Posted on 2/27/2010 @ 5:30 PM
@Phil
I think what you have is fine. You want the root view model to control creation of the child view model. This is pretty similar to how forms are handled in Silverlight.FX.

In a sense, child view model is just a model like any other class, and ChildView is a control just like any other control in the view that is data-bound. If however you are in fact using Silverlight.FX and want ChildView to have a logically different model, so contents of ChildView never see the root view model when they ask for the model, then I'd suggest the following hookup instead:

<ChildView fxui:View.Model="{Binding ChildViewModel}" />

In fact, I think anytime you explicitly see DataContext being set in the view is a red flag to me. To me DataContext is about infrastructure, you never set it. You either set View.Model, or ItemsSource etc. The underlying infrastructure such as View in Silverlight.FX or ItemsControl etc. set DataContext, on behalf of the app developer.

Steve

Posted on 2/28/2010 @ 4:00 PM
A bit OT here, but I'd like to use Silverlight.FX for many of the reasons you mention (ie. in particular, no more 'ICommand'), however, I need Silverlight.FX to be usable within Prism. Maybe that has changed from my last use of Silverlight.FX. So I have a need to utilize Silverlight.FX within an existing framework.

Steve

Posted on 2/28/2010 @ 4:02 PM
And one more thing... have you ever considered creating a good example of Prism along-side Silverlight.FX. To me, to have the power of both at same time would be great for building composite silverlight apps. You and Prism need to hook up ;)

Nikhil Kothari

Posted on 2/28/2010 @ 10:52 PM
@Steve
Could you please tell me about your experience with Silverlight.FX and Prism? You mention things may have changed... I'd love to hear what issues you hit. I'd also love to hear which parts of Silverlight.FX you want to use in conjunction with Prism, and which parts of Prism are interesting to you.

Feel free to use my contact form, as that might be more appropriate channel for discussion than comments here.

Manuel Felício

Posted on 3/16/2010 @ 2:59 AM
Hi,

I also use convention over configuration and I have Unity resolve my views, viewmodels and models based on conventions and actions, for example, edit an entity, search entities of a specific type, etc.

With this aproach of conventions and actions i also have my prism modules register automatically all views/viewmodels on startup (doing some reflection but hey..it runs only once in the app).

I'm working on a blog post on this approach and I will also cover architecting WCF RIA Services apps with PRISM and MVVM.

Its nice to know that Silverlight.FX is moving in that direction as well! Good job

Kasimier Buchcik

Posted on 4/20/2010 @ 11:13 AM
Does any of the proposed approaches inject the ViewModel into the resources of the View so that we can reference it with StaticReference?
Using fxui:View.Model would not allow for this, because it is processed after the components of the view have been initialized, right?

AFAIK, if the ViewModel is not referenceable via StaticReference then we cannot access it in DataTemplate(s), which would be quite unfortunate.

Maybe a combination of fxui:View.Model and a dedicated resource locator could do the trick. The locator would reside in the resources of the UserControl and pick up the ViewModel provided by fxui:View.Model.
This would also solve my current issue with propagating the ViewModel to nested UserControls. But I dunno how (if it's possible at all) to do that. See http://forums.silverlight.net/forums/p/176766/399147.aspx#399147.

Kasimier Buchcik

Posted on 4/20/2010 @ 12:31 PM
OK, the above proposed combination of the fxui:View.Model and the dedicated resource locator can be found here:
http://forums.silverlight.net/forums/t/176766.aspx
(further down the thread)
Post your comment and continue the discussion.