I've been developing a very large LOB app using my flavor of M-V-VM which I call M-V-MC (Model-View-ModelController), which is a kind of a combination between M-V-C and M-V-VM. I had posted this answer regarding how views get instantiated in M-V-VM to the question "what-are-the-most-common-mistakes-made-in-wpf-development".
Sam made the following comment regarding my answer:
This creates a follow-up-question: how do you create the views? I use RelayCommands to bind actions from the view to the ViewModel, so the view does not even know an action has fired, does not know he should open a new view. Solution: create an event in the VM for the View to subscribe to?
When I originally started M-V-VM development I had this notion that EVERYTHING should live in the ViewModel, and have studied a lot of examples from guys like Josh Smith and Karl Shifflett. However I have yet to come up with a good example of when a command needs to live in the ViewModel.
For instance, let's say I have a ListView that displays Customers, and a button that I click to allow me to edit the currently selected customer. The ListView (View) is bound to a CustomerVM (ViewModel). Clicking the button fires the EditCustomerCommand which opens a popup window which allows me to edit all the properties of the CustomerVM. Where does this EditCustomerCommand live? If it involves opening a window, (UI functionality), shouldn't it be defined in the code-behind of the view?
Does anyone have any examples of when I should define a command in the View versus the ViewModel?
Matthew Wright states below:
New and delete from a list would be good examples. In those cases, a blank record is added or the current record is deleted by the ViewModel. Any action taken by the view should be in response to those events occurring.
So if I click the new button, what happens? A new instance of the CustomerVM is created by the Parent ViewModel and added to it's collection right? So how then would my editing screen get opened? The view should create a new instance of the Customer ViewModel, and pass it in to the ParentVM.Add(newlyCreatedVM) method right?
Let's say I delete a customer record via the DeleteCommand living on the VM. the VM calls into the business layer and tries to delete the record. It can't so it returns a message to the VM. I want to display this message in dialogbox. How does the view get the message out of the command action?