I'm starting on my first WPF project using MVVM and Castle Windsor. I'm following the fairly standard approach of injecting a view model into its view's constructor, which then sets its DataContext to the view model. What I'm not clear on is how/where to perform any UI "initialisation" that I want to happen right after the window has loaded (in my case I want to instantiate a number of user control "widgets" and put them on the window's canvas).
Presumably I can't do this in the constructor of the window's view model, as it will have been called prior to the view's InitialiseComponent being called. Besides, how would I even reference the canvas from the view model, which should have no knowledge of the view?
As part of trying to solve this, I created a "DesktopManager" component responsible for adding user controls to the canvas, but I'm getting circular references:-
the view obviously has a dependency on the view model
the DesktopManager has a dependency on the view (it needs to access the Canvas),
the view model has a dependency on the DesktopManager (so it can tell the DesktopManager to create the widgets).
The DesktopManager still won't help me though - referring back to my earlier question I don't know how/where to call it to create the widgets. I'm clearly going about all this the wrong way, and perhaps answering my earlier question will solve this one too!
Any suggestions appreciated.
Andrew
If you are looking for a way to execute code in your view model once the view has been loaded, I would suggest that you bind the Loaded event of the view to a command in your view model.
Look here for one way to bind events to commands:
http://www.danharman.net/2011/08/05/binding-wpf-events-to-mvvm-viewmodel-commands/
Related
I work on a custom WPF Diagram Control. The control has a method that arranges the elements in the Diagram and I need to add MVVM support to call this method from my View Model.
At the moment I am a bit confused how to implement this and I hope that someome can point me to the right direction.
Maybe you need to rethink your concept. What needs to be re-aranged?
Think of ViewModel the logic behind a view and the view should be as dump as possible without any logic.
I assume also that the "arranges" method should be well tested and this could also be "easier" done on a ViewModel (if done right). Your best bet would be to place all logic in the ViewModel.
From the top of my head I could think of a DiagramViewModel with an ObservableCollection<ShapeViewModel>. ShapeViewModel can either be a base class or a concrete class which could also have some information about the location of the shape etc. The communication between the view models can be done via a Messenger (MVVM Light Messenger) or EventAggregator https://msdn.microsoft.com/en-us/library/ff921122.aspx.
If you still want to leave your architecture as you have it and want to execute a method on the view I would abstract it in a service. IDiagramUpdateService.
Look at following article which gives you good insights in communication between views and view models (and vice versa).
https://msdn.microsoft.com/en-us/magazine/jj694937.aspx
You'll find great information for both approaches.
HTH
Thanks for the quick response to my question.
I think my concept was a bit wrong, since the ViewModel should have no reference to the View.
What I would like to achieve is that I can place a button in the Main Window that calls the Arrange Method in the Custom Control.
I realized this by adding a RoutedCommand to my Custom Control.
And the Command Property of the button on the main window is bound to this RoutedCommand.
So the ViewModel is no longer involved in calling this method. It just manages the items that are shown in the Custom Control.
I've been puzzled by this for a while. I am writing quite a large RibbonWindow WPF application using the MVVM pattern. The screen has a RibbonBar menu along the top and the rest of it displays the various Views. Some Views contain other Views and some of these have buttons that launch child Windows.
So far, I have been doing this from the View code behind file, but I'm aware that these files are supposed to be empty when using MVVM. I could move the child window launch code to the ViewModel, but then I would need a reference to the main RibbonWindow (to set as the child window owner) and that doesn't seem right.
Any advice or tips on how this is normally achieved using MVVM would be greatly appreciated.
I usually handle this by creating some sort of WindowViewLoaderService. When your program initializes you register your Window's and your ViewModels with code something like this:
WindowViewLoaderService.Register(TypeOf(MainWindowView), TypeOf(MainWindowViewModel));
WindowViewLoaderService.Register(TypeOf(MyWindowView), TypeOf(MyWindowViewModel));
Then when you can for example call into this service from your ViewModel and all you have to reference is your other ViewModel. For example if you are in your MainWindowViewModel you might have code like this:
var myChildWindowVM = new MyWindowViewModel();
WindowViewLoaderService.ShowWindow(myChildWindowVM);
The WindowViewLoaderService would then look up what View is associated with the specified ViewModel you passed it. It will create that View, Set its DataContext to the ViewModel you passed in, and then display the View.
This way your ViewModels never know about any Views.
You can roll your own one of these services pretty easily. All it needs to do is keep a Dictionary with the key being your ViewModelType and the value being your ViewType. The Register method adds to your dictionary and the ShowWindow method looks up the correct view based on the ViewModel passed in, creates the view, sets the DataContext, and then calls Show on it.
Most MVVM Frameworks provide something like this for you out of the box. For example Caliburn has a slick one that just uses naming convention its called ViewLocator in this Framework. Here is a link that summarizes: http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/04/mvvm-study-segue-introducing-caliburn-micro.aspx
Cinch on the other hand calls it a WPFUIVisualizerService which you can see in action here:
http://www.codeproject.com/KB/WPF/CinchIII.aspx
These should help get you rolling.
Well, one remark to start with is that, "Having no code AT ALL in the code-behind" is actually a "myth". If you want to be pragmatic, and you see that having some code (as little as possible would be better), will make your life easier and solve your problem, then you should go with that.
However, in this situation, there are actually some loosely coupled ways to do this. You could have a service that does the interaction for you. You initiate the interaction with the user from the ViewModel, the service takes care of that (by showing a ChildWindow for example), and gives you back the user's reponse. That service can be mocked for testing easily. And it can be tested seperately.
That is, if you want to do things yourself. If you want a framework to do the heavy lifting for you, you can check out the InteractionRequest functionaity offered by Prism. Here's the MSDN article that talks about adanced MVVM scenarios which includes a section on User Interaction Patterns. That's the way I do it, and it's pretty simple, elegant and straightforward.
Hope this helps :)
To take Matt's answer one step further, you can have all your view's be a user control. Then create a ViewContainer, which is a window with your data templates (as you described).
Then you just ship the viewmodel you wish to open over to the window service, which sets the DataContext. The service would then open the window and the contentcontrol will resolve the correct view for the viewmodel.
This means all the registration is done in the XAML and the window service just knows how to do just that...open and close windows.
This is an old post, but maybe this'll help someone along the way: I use MVVM, and raise events for opening child windows from the ViewModel back to the View. The only code behind is handling the event, opening the window, setting owner of the child window and that's pretty much it. In the viewmodel, if the eventhandler is null, then it's not subscribed to by the view and doesn't fire. The VM does not know about the view. The code is pretty simple also and only takes a few lines.
In this situation View should handle the opening of the child windows.
However, ViewModel might drive the creation of the windows, but calling into View to create a new Windows.
This will save the logic of MVVM pattern: ViewModel has the "brains" but is not involved in a particular window creation.
ViewModel only is used to present system state and UI logic. One viewmodel may be referenced by multiple views. It have no knowledge of UI specific code like parent/child relationship, position, layout, size etc. So it is better to pop child window in view's code-behind with ViewModel's state changed event or command event and event arguments. In this way you can specify which one is the parent view in the UI layer.
In the MVVM (Model-View-ViewModel) pattern should the ViewModel reference the view. I would think that it should not. But how should the following scenario be handeled? I have a view that has a tab control as the main container, the viewmodel for this view implements a command to add a new tab to the tab control. The easy way would be to allow the viewmodel to reference the view and then in the command implementation to just programmatically add the new tab to the tabcontrol in the view. This just seems wrong. Should I somehow bind the tabcontrol to the viewmodel and then implement a data/control-template to add the new tabs. I hope this makes some kind of sense to somebody :)
In "pure" MVVM, the ViewModel shouldn't really reference the View. It's often convenient, however, to provide some form of interface in the View whereby the ViewModel can interact with it.
However, I've found that I almost never do that anymore. The alternative approach is to use some form of attached property or blend behavior within your View, and bind it to your ViewModel properties. This allows you to keep the View logic 100% within the View. In addition, by creating a behavior for this, you create a reusable type that can be used to handle this in every ViewModel->View interaction. I strongly prefer this approach over having any View logic within the ViewModel.
In order to demonstrate this technique, I wrote a sample for the Expression Code Gallery called WindowCloseBehavior. It demonstrates how you can use a Behavior within the View bound to properties in the ViewModel to handle controlling a Window's life-cycle, including preventing it from being closed, etc.
Reed and Dan covered the general approach but in reference to your specific case, TabControl is an ItemsControl and so can bind its ItemsSource to a data collection in your ViewModel representing the set of tabs to display. The UI for each type of tab can then be represented by a DataTemplate specific to the data type of an item (either using DataType or a DataTemplateSelector). You can then add or remove data items as needed from your VM and have the tabs update automatically without the VM knowing anything about the TabControl.
I find that it's often a helpful compromise to expose an interface on the View that handles View-specific functionality. This is a good way to handle things that are awkward to accomplish with pure binding, such as instructing the form to close, opening a file dialog (though this often gets put in its own service interface) or interacting with controls not designed well for data binding (such as the example you provided.)
Using an interface still keeps the View and ViewModel largely decoupled and enables you to mock the specific IView during testing.
One of us is missing something obvious. Your tab control is an ItemsControl. You should bind the ItemsSource of your tab control to an ovservable collection in your view model. When you handle the command in your view model to add a tab, you simply add a new element to this collection and, voila, you've added a new tab to the control.
I'm working in a WPF project, I'm using the MVVM patter in my project.
I created a user control (also in WPF) and I want to use it in my project, now, my problem is that I have a method in my user control that I need to call from my View Model, but I don't know how to do that, how to bind to the method inside my control from the view model.
If I use code behind, obviously there is no problem since I have a direct reference to my control, so I can do "mycontrol.MyMethod();"m, but of course, doing in this way will go against the logic of the MVVM pattern.
I tried to use a Dependency Property in my user control, and use that Dependency Property to bind to it in the xaml of my project but it didn't worked, the compiler says that the property was not found or is not serializable.
So I will appreciate if someone can share some light about how can I accomplish this.
Edited
As far as I understand you have the view, which is all the GUI, then you have the model, which is all the logic, and them you have the view-model which is like an intermediate layer used to bind the view with the model, right?
In this way I have developed my project, however I came to the problem that I need a custom control, a TextBox that remember what the user entered, and when he start typing, if there are words that start with that letter, those words are shown as a suggestion, as Google does it.
This TextBox is used as a search filter; so I created a user control to do this, I added a method to my user control to allow whatever application that uses my control to add items to an internal array that holds all the strings that the user has entered.
I created a user control because I couldn't find any control that behaves the way I want.
So my problem is when I add my user control to the main project, because I need to someway be able to call the method that add the items to the internal array, but maybe I'm doing things the wrong way, so if any of you has a better idea, I will appreciate if you shared it with me.
You should never call View methods from ViewModel, and vice versa.
Make a property (ObservableCollection?) on your ViewModel, it will have CollectionChanged event, subscribe to it to monitor changes (if needed).
When you add an item to the collection in your ViewModel, GUI will be updated accordingly (you have to perform the Add() operation on GUI thread, btw).
If you need to change the current position in your list, there are colections for that (CollectionViewSource, etc).
If you really really need to pass a string to your control, make a DependencyProperty and bind it OneWay to your ViewModel's property. When you set the value, it will call PropertyChangedCallback on your DependencyProperty.
Why does the consumer of the user control need to maintain the control's internal array? That seems like you've exposed an implementation detail that you don't need to.
Why not simply make that array a dependency property (and an IEnumerable<string> or ObservableCollection<string> besides)? Then you can simply create the corresponding property in your view model and bind it to the control. It also makes the control considerably more versatile.
You shouldn't call something in the View from the ViewModel since that breaks the model.
If the reason you want to call the method in the user control is to do with UI only, I don't see anything wrong with doing it from the view - the view's cs and the view's xaml are in the same "space" in the model. You can be overly-purist in wanting to have lean and mean view cs files.
I am implementing MVP/M-V-VM in WPF and I'm having good luck with it so far. However, I don't see how this model supports implementing Modal dialog boxes. I've derived my work from Crack.NET (http://www.codeplex.com/cracknetproject) to learn how this stuff works.
I have a ShellView view (which is just XAML) that has a menu on it. The menu binds to a command in the ShellModelView that says "EditPreferences".
The ShellModelView implements the ICommand for EditPreferences and here we want to put up a dialog box to let the user edit preferences for the application.
Several problems here:
1. The ShellModelView doesn't have a reference to the ShellView to properly parent the dialog. The ShellModelView is the DataContext of the ShellView but I don't see a backreference that's setup.
2. The ShellModelView shouldn't be loading explicit UI anyway. So what's the proper interaction model here?
3. How do I build up my PreferencesDialog so that it's properly separated between logic and view as well? PreferencesDialog itself needs to be a Window so you can call ShowDialog on it, but that means you need a reference to the Window (e.g. View) in order to instantiate it. Ideally I should be able to unit test the code/validation within PreferencesDialog without instantiating the view (using a Mock view perhaps?).
Perhaps this is not the appropriate way to look at it, but this is the approach I take with M-V-VM in WPF. Opening windows and dialog boxes or an "EditPreferences" view are UI specific functions. If I were to rewrite the your entire UI replacing all of the views, I may wind up combining the "EditPreferences" view with another view, and therefore never want to open it in another screen. If this were tied to the ViewModel, it would be difficult to get around. In this particular situation, I would have a button or menu item in my "ShellView" that creates a new instance of my "EditPreferences" view, and then passes in the "EditPreferences" ViewModel which may either come from a property in my "ShellViewModel", or perhaps my "EditPreferences" view instantiates the ViewModel itself.
Here is a similar question on SO that basically says the same thing: M-V-VM Design Question. Calling View from ViewModel
You will need a controller in your case. The controller should be in charge for showing the preference dialog window.
As I can envision it the controller should be responsible for creating the ShellModelView and binding view's DataContext to it. The controller should be also responsible for handling command execution of EditPreferences. In the execution logic the controller will create a new PreferencesDialog and its corresponding view model.
You can find similar patterns in Prism if you haven't already did it. You can also reuse the DelegateCommand provided there :)
Have the PreferencesDialog implement a interface that is one of the properties of the EditPreference command. The command would interact with the dialog through the interface. For Unit Testing the mock object would implement the interface instead.
The dialog class then can reside on your highest layer.
My 2 cents is:
Pass some kind of viewfactory contract as the command parameter or inject a viewfactory contract into the view model. The view model will them use the viewfactory to create any modal/non modal views it needs. The viewfactory could also take in as a parameter of its Show/ShowModal method a viewmodel to display. Furthermore, the viewfactory could use a datatemplate to display any viewmodal passed in as a parameter.
Add a ShowViewModel property to the viewmodel in question. A DataTrigger could then watch for this property and when it is of a particular type show the view, etc.