views:

52

answers:

4

I am a big proponent of the MVVM pattern with Silverlight. Currently I wire the ViewModel up to the View by newwing up the ViewModel in the code behind of the view, thusly:

public partial class SomePage : UserControl
{
    public SomePage()
    {
        InitializeComponent();

        // New up a ViewModel and bind to layout root
        var vm = new SomeViewModel();
        LayoutRoot.DataContext = vm;
    }
}

And then all the binding is handled in the View and all the logic is handled in the ViewModel, as the pattern intends.

However, wiring them up this way means that the designer doesn't work well, and I can't use Expression Blend design time data. I know that there are libraries such as MVVM Light that will help to get all this working, but I prefer not to bring in a library, as it is "one more thing" to have to deal with.

Is there a simple pattern for getting MVVM wired up in Silverlight while maintaining designer functionality, especially in Blend? I've done some Googling but there are so many outdated articles out there and so much confusion between WPF and Silverlight and older versions that I have a hard time figuring out which to use.

BTW I'm focused on SL4 with VS2010 if it matters.

+1  A: 

I've run into similar issues designing WPF applications. One trick I've learned is to declare an xmlns so you can embed an array of objects in XAML:

xmlns:coll="clr-namespace:System.Collections;assembly=mscorlib"

You can then drop an ArrayList of just about anything into the XAML:

<coll:ArrayList x:Key="questions">
    <local:QuestionItem Title="FOO"></local:QuestionItem>
</coll:ArrayList>

You can then set the ItemsSource of a grid, listbox, etc to the array:

<ListBox x:Name="lstStuff" ItemsSource="{StaticResource questions}" />

This technique will allow you to "preview" the look and feel of list-style controls in the designer. It doesn't solve all problems with visual prototyping, but it goes a long way and can be adapted to several different scenarios.

You could, for example, declare your local namespace as an xmlns, then drop mocks of your ViewModel into the Resources of the window or control. I haven't tried this but theoretically you could get a complete design-time preview.

Dave Swersky
So in your example you would set the ItemsSource of lstStuff to something else at runtime? Would you do this in the codebehind?
jkohlhepp
I usually set the ItemsSource in the XAML while I'm testing/prototyping, then remove the ItemsSource setting to test the app. Removing the ItemsSource setting may or may not be necessary depending on how you populate the list control
Dave Swersky
+1  A: 

There are a few methods you can use.

First, let Expression's Sample Data and design-time attributes (i.e. d:DataContext) take over in the designer. In your code, you would simply condition the view model binding:

if (!DesignerProperties.IsInDesignTool)
{
   var vm = new SomeViewModel();
   LayoutRoot.DataContext = vm; 
}

Second, you can have a special design-time view model that you bind instead:

LayoutRoot.DataContext = DesignerProperties.IsInDesignTool ?
    new DesignViewModel() : new MyViewModel(); 

Finally, another way is to manage the data within the view model. I don't like this because it spreads the responsibility across all view models, but you have more precision:

// constructor
private Widget[] _designData = new[] { new Widget("Test One"), new Widget("Test Two") };

public MyViewModel()
{
   if (DesignerProperties.IsInDesignTool)
   {
       MyCollection = new ObservableCollection<Widget>(_designData);       
   }
   else 
   {
       MyService.Completed += MyServiceCompleted;
       MyService.RequestWidgets();
   }
}

private void MyServiceCompleted(object sender, AsynchronousEventArgs ae)
{
   // load up the collection here
}

Hope that helps!

Jeremy Likness
Hmm...all of those methods deserve some experimentation. Thanks for the feedback. Could you provide any more details on the first method? Is there some documentation or blog post I could read?
jkohlhepp
Sure. I use design-time properties extensively in the reference Silverlight application I built here: http://csharperimage.jeremylikness.com/2010/06/advanced-silverlight-applications-using.html
Jeremy Likness
+2  A: 

What you are looking for is "Blendibility". MVVM Light has a concept of the ViewModelLocator and I'm using it on a project with great results.

Here's a great post by Roboblob on the topic. http://blog.roboblob.com/2010/01/17/wiring-up-view-and-viewmodel-in-mvvm-and-silverlight-4-blendability-included/ This post has an example solution so it really helps in the understanding. Rob improves on the MVVM Light implementation and I think does a good job.

itchi