How to access control in viewmodel - wpf

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

Related

How to set data context where Views and View models in separate library

My Projects are
student.shell.client
student.views
student.viewModels
Modules.student
student.views has student.viewModels reference, in stuent.views used ViewModelLocator.AutoWireViewModel= true, its not resolving the view model. Is this is not a good practise to have views and view models in different project.
How to wireup views and view models here?
Yes, you can have your ViewModels in a separate assembly, you just have to tell the ViewModelLocator about the new rules to use to find them. In this blog you can see how to change the conventions to use your own convention:
http://brianlagunas.com/getting-started-prisms-new-viewmodellocator/
Very easy!
BTW #R. Richards, Prism uses DI when resolving the VMs automatically and all dependencies will be resolved with no issues and without injecting into the View ctor. This way, the View project will not have to even reference the ViewModel project. As long as all the assemblies are loaded into the AppDomain, it will just work.
Do you really need separate assemblies for the views and view models? Likely not. If you want to use the view model locator, then the easiest way is for them to be in the same project/assembly.
Either that, or new up the view models in the views code behind. This will work okay if your view models don't have any dependencies. Some frown on this because the coupling between the view and view model is rather tight.
public partial class StudentView : UserControl
{
public StudentView()
{
InitializeComponent();
DataContext = new StudentViewModel();
}
}
Or, you can have the IoC container provide the view model in the views contructor.
public partial class StudentView : UserControl
{
public StudentView(StudentViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
This second option (IoC) is a better option given the fact that your view models will likely have dependencies that the container can provide, too.
Hope this helps.

Setting DataContext in Catel with WPF

So I've started looking at the Catel MVVM framework and it looks like it will solve a couple of problems I have encountered, but I have one really silly issue. I think I'm just missing something small.
I took one of my smaller WPF projects to switch over the Catel as a way for me to learn it. I have a simple 'Player Registration' form, with fields like name and surname. I recreated my original view model by using the vm codesnippet and all is good, all the properties and attributes I've set up as I've read in the documentation.
I then changed the UserControl I used for 'Player Registration' (PlayerRegistrationView) to a catel:UserControl. I placed PlayerRegistrationView on a standard WPF Window (nothing else, just a xmlns for the View and the view as the only content on the window, no attributes)
But here is my problem:
I have a MainWindow with a button on to open the Window for the player registration. The on-click event simply is this:
private void ButtonPlayerClick(object sender, RoutedEventArgs e)
{
var playerRegistration = new PlayerRegistrationDialog
{
Owner = this,
DataContext = new PlayerRegistrationViewModel(),
};
playerRegistration.Show();
}
Running my program and then clicking on the button results in an NotSupportedException on my PlayerRegistrationView: The view model of the view could not be resolved. Use either the GetViewModelType() method or IViewModelLocator
I tried making the ViewModel a static resource on the window and setting the datacontext there, but it produces the same error.
I am at a loss. What have I missed?
Thanks
The whole point of Catel is that it automatically wires up all the views and view models. The "complex" thing that you are trying to achieve is that you have a view which is placed on a window. You want the window to have the same data context as the view in order to do some stuff in the window as well.
In Catel, it is possible to place any view with datacontext management on a DataWindow (window in Catel). Then it will work like this:
DataWindow
|=> View
If the DataWindow and the View share the same view model type, then they share the same view model. For example:
PlayerRegistrationWindow => derives from catel:DataWindow
PlayerRegistrationView => derives from catel:UserControl
Since both start with PlayerRegistration, they will both be resolved to PlayerRegistrationViewModel automatically.
To show the window, the only thing you have to do is this:
var viewModel = new PlayerRegistrationViewModel();
var uiVisualizerService = ServiceLocator.Default.ResolveType<IUIVisualizerService>();
uiVisualizerService.Show(viewModel);
All will work automatically and you don't have to worry about setting any datacontext yourself.

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

Can I use UnityCOntainer in View's codebehind ? (MVVM)

Can I use UnityContainer in View's codebehind when I want to write good MVVM program?
this.DataContext = uc.Resolve<MainViewModel>();
If you're asking if you can, yes.
If you're asking if you should, the answer is still yes.
ServiceLocator is an anti-pattern, you shouldn't be using it. The reason it's an anti-pattern is because it allows for objects to be resolved inside a class at any time, reducing the usefulness of your DI and making your code harder to unit test.
My suggestion would be to do one of the following:
a) Inject the viewmodel into the view through it's constructor. Resolve the view using Unity so that it resolves all the views dependencies (the view model) for you.
So:
public partial class View:UserControl,IViewFoo
{
public View(IViewModel viewModel)
{
DataContext=viewModel;
}
var view=_container.Resolve();
}
b)
Use an attached property to inject the viewmodel into the DataContext for you. MEFEDMVVM and MVVMLite both do this (look them up on Codeplex)
c)
Follow a convention-based approach where the viewmodel gets assigned to the view based on them having compatible names (MainView.cs and MainViewModel.cs). Caliburn Micro does this and is very nice to use. This can also be found on CodePlex.

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").

Resources