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

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();
}

Related

How to access control in viewmodel

My app is in WPF,VS 2010 PRISM and Unity. i want to access Views Dockpanel control in viewmodel when constructor initialization for Adorner. any help would be appreciated.
Yup. The correct response is you DON'T. In MVVM, the VM should have no knowledge of Views at all. You should be binding the View to the View Model.
However, there are of course certain cases where this pattern/model breaks down. At this point you can consider using the MVPVM pattern *. The class that MAY access the View is called the Presenter.
*Seriously, I'm not even kidding on this one. This link is a Microsoft magazine link.
Simple way is that you can resolve IUnityContainer of View and can access control like:
readonly IUnityContainer _container;
public CONSTRUCTOR(IUnityContainer container)
{
_container=container;
var resolved = _container.Resolve<IEmployeeView>();
// cast your resolved view as View.
var views = resolved as YOURVIEWNAME;
// and get control.
var controls = views.YOURDOCPANELNAME;
}

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

Dynamically generating ViewModel for tooltips in WPF MVVM

I have a list of items representing packages in an MVVM control.
When you hover over the tooltip it needs to go to the database for additional information, lets just call it 'PackageDetails' for simplicity. I know how to handle the database loading with a ViewModel class but I'm having trouble figuring out when to instantiate it.
Approach 1) Have a 'lazy-load' property in the 'Package' object so when the tooltip is triggered the viewmodel will be created and immediately access the database.
This approach isn't ideal because each 'Package' object isn't a true viewmodel and came from WCF objects originally.
Approach 2) Use a converter as explained in this Josh Smith blog entry. His example seems to fit a converter well, but I don't think it really suits my situation well.
Approach 3) Somehow create a viewmodel in the XAML, but this seems like a bad idea.
What's a good approach to dynamically generate a viewmodel for a tooltip using MVVM
?
Binding models ( in your case the packages ) to the view only works for very simple situations where there is no more "processing" or business logic to implement.
I have experimented with a few options and in the ended up creating a VM wrapper for just about all my models. Going down this path makes having a tooltip property straight forward.
The other option that i have experimented with is to use partial classes to extend the wcf models. This works unless you are using dataannotations for validation ( wcf and dataannotations dont work together properly )
if you decide to wrap your models with a vm, then instantiating your list of VM wrappers is just one line of code using linq and lambdas
assuming you have a constructor on your VM that accepts your model as a parameter.
var listPackageVMs = new ObservableCollection<PackageVM> ( listPackageModels.Select(model=> new PackageVM(model)));
You could create a partial class to Package. I would avoid placing data access logic in an entity class, but this is the cheap and easy way.
namespace WCFServiceNamespace
{
// Since WCF generated entities are partial classes, we can inject features
public partial class Package
{
private readonly IDataAccessor _DataAccessor;
public Package()
: this(DataAccessor.Instance) // how you choose to inject a data accessor is up to you
{
}
public Package(IDataAccessor dataAccessor)
{
_DataAccessor = dataAccessor;
_ToolTip = new Lazy<string>(GetToolTip);
}
private readonly Lazy<string> _ToolTip;
public string ToolTip
{
get
{
// executes GetToolTip when the Value property of Lazy<T> is accessed
return _ToolTip.Value;
}
}
private string GetToolTip()
{
// we're assuming we can retreive the tooltip by ID, and that PackageId is defined in the generated WCF entity
return _DataAccessor.GetToolTipByPackageId(PackageId);
}
}
}

MVVM model instantiation

Following WPF MvvmFoundation, linking the View with the ViewModel has many choices like described on http://www.paulstovell.com/mvvm-instantiation-approaches.
However their example has nothing about how to link the ViewModel with the Model.
Traditionally I created the model first and then one or more views that render it. It seems that MVVM pushes people to create the View, which creates the ViewModel, which create the Model. I hope it's not the case as wiring a complex business model with various ModelView can else be tough.
How do you instantiate your business model classes in MVVM and link them with your ViewModels?
I normally pass Model objects as constructor params to VM. I use App class as the controller which will initialize MainWindow, MainWindowViewModel with the main model. There after the MainWindowViewModel takes care of initializing other VMs with appropriate model objects.
private void Application_Startup(object sender, StartupEventArgs e)
{
mainWindow = new MainWindow();
mainWindow.DataContext = new MainWindowViewModel(new Model());
mainWindow.Show();
}
You create your BusinessModel classes inside your ViewModel.
So in your CustomerViewModel you would say this.CurrentCustomer = new CustomerModel(), and your CustomerView would bind to the CurrentCustomer property on the ViewModel
If you are interested, I wrote up a simple sample using MVVM as an example of how the View, Model, and ViewModel interact.
I use dependency injection/MEF to do this. Just export all of my model classes all the way down the chain, and have them imported for me automatically into the ViewModel constructor.
I take a variety of different approaches depending on the situation. I've found that when it comes to getting this data linked, one size does not fit all.
For simple cases, I will have the ViewModel and the Model be the same thing. Obviously not that good for all cases, but sometimes there is just no need to go the extra mile to split the M from the VM. (Great for cases where you have, say, listbox items that have scant information)
Sometimes, especially when the model is a chunk of code you don't have access to (written by another developer) it is easy to subclass the model, and add all of your VM things (observable properties, etc.) on to it.
Lastly, I will use the approach that is mentioned by Souvik. Construct the VM with the model information that you want to use as a parameter, or allow it to be passed in otherwise. This is probably the most common approach for my larger and more complex Model / ViewModel relationships.
I am auto-passing IRepository instance to VM constructor using IoC container and everything VM needs to do with models is done via this repository. Repository is class which: Create, read, update and delete data. When I need to show some view (window), I use IViewService.ShowDialog(viewModel As ViewModelBase). In implementation of IViewService, there are views registered with VMs, so VMs only need to know other VMs and not their views (like "Show me view for this view model").

Getting Silverlight MVVM working with Expression Blend design time data?

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.

Resources