Getting Silverlight MVVM working with Expression Blend design time data? - silverlight

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.

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!

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.

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.

Related

A Controller for MVVM

I'm working on a WPF project that's a mishmash of code-behind xaml/xaml.cs and a few not-quite ViewModels as well.
(Disclaimer: Until recently I've had very little in the way of WPF experience. I can design and lay-out a Window or UserControl fairly proficiently, and I think I get the hang of separating an MVVM ViewModel from the View and doing binding wire-ups, but that's the limit of my experience with WPF at present.)
I've been tasked with adding some new features to the program, such that it looks like converting it to use MVVM properly first is going to be necessary.
I'll demonstrate a specific problem I'm facing:
There is a View called SettingsWindow.xaml that I'm working with. It's a set of textboxes, labels and whatnot. I've stripped-out all of the View data into a ViewModel class which resembles something like this:
class SettingsViewModel : ViewModelBase {
private String _outputDirectory;
public String OutputDirectory {
get { return _outputDirectory; }
set { SetValue( () => this.OutputDirectory, ref _outputDirectory, value) ); }
}
// `SetValue` calls `PropertyChanged` and does other common-tasks.
// Repeat for other properties, like "Int32 Timeout" and "Color FontColor"
}
In the original ViewModel class there were 2 methods: ReadFromRegistry and SaveToRegistry. The ReadFromRegistry method was called by the ViewModel's constructor, and the SaveToRegistry method was called by MainWindow.xaml.cs's code-behind like so:
private void Settings_Click(Object sender, RoutedEventArgs e) {
SettingsViewModel model = new SettingsViewModel(); // loads from registry via constructor
SettingsWindow window = new SettingsWindow();
window.Owner = this;
window.DataContext = model;
if( dialog.ShowDialog() == true ) {
model.SaveToRegistry();
}
}
...but this seems wrong to me. I thought a ViewModel should consist only of an observable data bag for binding purposes, it should not be responsible for self-population or persistence, which is the responsibility of the controller or some other orchestrator.
I've done a few days' worth of reading about MVVM, and none of the articles I've read mention a controller or where the logic for opening child-windows or saving state should go. I've seen some articles that do put that code in the ViewModels, others continue to use code-behind for this, others abstract away everything and use IService-based solutions, which is OTT for me.
Given this is a conversion project where I'll convert each Window/View individually over-time I can't really overhaul it, but where can I go from here? What does a Controller in MVVM look-like, exactly? (My apologies for the vague terminology, it's 3am :) ).
My aim with the refactoring is to separate concerns; testability is not an objective nor would it be implemented.
I personally disagree with putting much in my ViewModels beyond the stuff that is pertinent to the View (it is, after all, a model of a View!)
So I use a Controller paradigm whereby when the View tells the ViewModel to perform some action (via a Command usually) and the ViewModel uses a Command class to perfrom actions, such as saving the data, instantiating new View/Viewmodel pairs etc.
I also actually separate my ViewModel and ViewData (the ViewModel 'contains' the ViewData) so the ViewData is puirely dealing with the data, the ViewModel with some logic and command handling etc.
I wrote about it here
What you need is called Commanding in WPF.
Basically you bind Button.Command to a ICommand property in your ViewModel and when Button is clicked you get a notification in ViewModel without using code behind and casing DataContext or whathever hacks you tried.
http://msdn.microsoft.com/en-us/library/ms752308.aspx

How to have Multiple unique instances of ViewModel using MVVM Light?

I am fairly new to following the MVVM pattern. I am using MVVMLight. I am wondering how have multiple unique instances of the ViewModel with MVVM Light. For exmaple I have an application that can open n number of windows. Each uses the same Viewmodel. I am curious in MVVM whats the best practive to give them there own instance.
If I follow the MVVM Light example the ViewModeLocator will have only a static instance which each window will end up using.
Thanks in advance.
Easy:
public EndingViewModel EndingViewModel
{
get
{
return ServiceLocator.Current.GetInstance<EndingViewModel>(Guid.NewGuid().ToString());
}
}
When resolving from the ServiceLocator make sure the call to GetInstance passes in a unique value to the method. In the above example I pass in a guid.
I really wouldn't build your objects manually as this defeats the point of having the Dependency Injection container in MVVM Light.
You are not obliged to use ONLY the static view models in the view model locator. That approach only makes sense if your views are sharing the same view model instance. For your scenario, you would simply new up an instance of your view model and assign it to the DataContext property of each window you create.
public void ShowChildWindow(Window parent)
{
var window = new WindowView();
window.DataContext = new ViewModel();
window.Show();
}

Implementing Telerik VirtualQueryableCollectionView with MVVM pattern

I have an application that was implemented using the Telerik RadGridView control and Caliburn.Micro MVVM framework. Because of some performance problems, I needed to implement the Telerik VirtualQueryableCollectionView in place of the direct control-to-ObservableCollection binding that was being used. The original code has the ItemsSouce property of the RadGridView was bound to the Prices property of the view model. I had to eliminate that binding and this in the code-behind:
public PricingView(PricingViewModel vm)
{
InitializeComponent();
var dataView = new VirtualQueryableCollectionView()
{ LoadSize=20, VirtualItemCount = vm.Prices.Count };
dataView.ItemsLoading += (sender, e) =>
{
var view = sender as VirtualQueryableCollectionView;
if (dataView != null)
{
view.Load(e.StartIndex, vm.Prices.Skip(e.StartIndex).Take(e.ItemCount));
}
};
this.PricesGridView.ItemsSource = dataView;
}
Since this code only deals with UI specific functionality and it is specific the the view implementation, I am comfortable that this code belongs in the code-behind rather than the ViewModel as it would be a departure from ther MVVM pattern to put a reference to VirtualQueryableCollectionView in the ViewModel. The part that I am not happy with is passing the reference to the ViewModel into the constructor of the View. Is there a good way to get the reference in the code-behind without having to pass the reference in the constructor?
Or is there a better way to do all of this?
My application is implemented with MVVM Light, in my case I used the VirtualQueryableCollectionView class in the ViewModel instead the View.
I did so because I think this class is very similar to the ObservableCollection although it is not part of the core classes.
Actually, VirtualQueryableCollectionView is not limited to the Telerik controls but many other standard controls like the ListView.
The fetch is in my case implemented in the Model.
void MainViewModel()
{
this.Traces = new VirtualQueryableCollectionView<MyEntityClass>()
{
// ViewModel also manages the LoadSize
LoadSize = this.PageSize,
VirtualItemCount = myModel.TotalCount
};
this.Traces.ItemsLoading += (s, args) =>
{
this.Traces.Load(args.StartIndex,
myModel.FetchRange(args.StartIndex, args.ItemCount));
};
}
Not sure what "performance problems" means, but I'm going to assume that means that when you fill the collection from the UI thread it blocks the application long enough it appears unresponsive.
There are two common solutions for this. First is to simply fill your collection from a background thread.
The naive implementation is to simply push the loading onto a ThreadPool thread, then use the Dispatcher to marshall the calls to add items to the ObservableCollection onto the UI thread.
A nicer approach (one that doesn't involve the ViewModel at all) is to use asynchronous bindings. You configure the fallback to some value that indicates to the user you are loading. Sometimes (depending on the situation) you can use a PriorityBinding to gradually fill your UI.
Other alternatives are to load and cache your data beforehand while displaying a splash screen. They're a bit different in WPF, it isn't like the old "display this form for a bit while I do work, then show the main form" mode of winforms. And, of course, there is always the classic data pagination. Its tough to code, but effective. Actually, I should say its tough in the UI. Its easy now in code (database.Skip(pageNumber * pageSize).Take(pageSize)).

How is the DataContext typically set?

I've created a new WPF project, and threw in a DataGrid. Now I'm trying to figure out the easiest way to bind a collection of data to it.
The example I downloaded seems to do it in the window c'tor:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
But then the bindings don't seem to appear in the Visual Studio's Properties window. I'm pretty sure there's a way to set the data context in XAML too... it would make me even happier if I could do it directly through the properties window, but all the Binding options are empty. What's the typical approach?
Edit: At 14 minutes, he starts to talk about other methods of setting the data context, such as static resources, and some "injection" method. I want to learn more about those!
What I typically do is use MVVM. You can implement a simplified version by setting the data context in your code behind and having a model type class that holds your data.
Example: In your code behind
DataContext = Model; // where Model is an instance of your model
then in your view
<DataGrid .... ItemsSource="{Binding SomeProperty}">....
Where SomeProperty is an enumerable property on your view model
You can also set a data context in XAML by using the DataContext property
<uc:SomeUserControl DataContext="{Binding AnotherProperty}"....
This will run your user control within the DataContext of the AnotherProperty on your model.
Note that this is grosely simplified but it'll get you on your way.
Have a look at the MVVM design pattern. This pattern is very suitable for wpf applications.
There is described where to store your data and how to bind your ui to the data.

Who sets DataContext in Silverlight MVVM

I have been reading about MVVM pattern from various sources like MSDN:
http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
In that article it says: Unlike the Presenter in MVP, a ViewModel does not need a reference to a view.
If the View (XAML) assumes it's DataContext is the ViewModel then where in the code is the following line:
view.DataContext = viewModel;
The ViewModel doesn't know anything about the view so it cannot set the datacontext. If I give the ViewModel the reference do I break the MVVM pattern? My other choice is to have some kind of Builder or extra Presenter whose only job is to wire the whole thing (wait for the loaded event of the View, set the DataContext).
I know different view's can share the same DataContext (e.g. set the DataContext only for the mainwindow and others will see it) but in many cases that is not possible at all nor even feasible.
This is a great question that has many answers. It all depends on how you want to architect your application. For instance, I use dependency injection to create my IViewModel, which in turn creates my IView and my IViewModel runs an IView.SetViewModel(this) on the constructor.
Other people may wish to use a more Blendable method by setting the DataContext in the Xaml:
<UserControl.DataContext>
<ns:CrazyViewModel />
</UserControl.DataContext>
Sometimes the DataContext can be implied so it is set by the framework, like in the instance of a DataTemplate used by an ItemsControl. This is also pretty common in desktop WPF because it supports typed DataTemplates.
So there really isn't a wrong way to set the DataContext, just as long as what you have separates concerns, is maintainable and is also easily testable.
Shawn Wildermuth has a great post about whether the View or ViewModel comes first:
http://wildermuth.com/2009/05/22/Which_came_first_the_View_or_the_Model
I like, and use, his marriage concept where a 3rd party class creates both the view and viewmodel, and then associates the two. It's worked well for me.
I use MVVM a lot in with Prism. In Prism I use Unity for dependecy injection. Therefore I have an interface for every class registered with Unity including the View.
The IView interface has a method like this:
void SetViewModel(object viewModel);
The ViewModel calls this method at the end of its constructor, passing itself as a parameter:
public ViewModel(IView view, ...)
{
...
this._view=view;
this._view.SetViewModel(this);
}
In the View.xaml.cs the IView interface is implemented. This will be the only code I add to the codebehind of the view:
public partial class View:UserControl, IView
{
public View()
{
...
}
public SetViewModel(object viewModel)
{
this.DataContext = viewModel;
}
}
As for my own usage, the ViewModel doesn't know the View, or any interface on the View. And most of time, the View doesn't know its ViewModel, even if it is less important. The VM is just transprted by the DataContext.
This ensures that the VM and V will remain highly independant. Links are established thoughout bindings, commanding, Behaviors, Triggers & so on. Even if VM is often highly related to a given view, I try to make it as generic as possible, so that I can switch the corresponding View, and / or adapt the View behavior without needing to update the VM, except if the architectural link between V and M is impacted !

Resources