silverlight - communicate between 2 view models in MVVM using commands - wpf

i am working on MVVM and using commanding in silverlight(DelegateEvent and ICommand)
I want something like this ,(say) i have 2 usercontrols , parent and child .
Parent is hosting the child , both have thier own viewmodels .
On parent i have a button and it executes a simple command , on execute of that command i want to update text in the child control's textbox . also we should be able to change something in child which can propagate to the parent .
Is events the best answer for this or i can have commands to update child/notify parent in some way.

There are several ways to go about this.
First, it is completely appropriate to have ViewModels that are composed of other ViewModels, as long as you are OK with them being coupled in that way. When you do that, they can just talk to each other using regular method calls.
Next, you can decouple a bit and use events. Nothing wrong with that. There is still an Observer -> Observable coupling, but they are less dependent upon each other.
Next, you can completely decouple and use something like an EventAggregator (Prism has a good one you can use). Shoot a Publish a message. The other subscribes. They don't know about each other at all.
I have used commands for this as well... but for ViewModel to ViewModel communication, I find this to be a bit awkward.

You should probably start with most obvious implementation where parent viewmodel simply holds a reference to a child viewmodel, and child viewmodel holds a reference to a parent viewmodel. Then when a command is executed on parent viewmodel it simply sets a value on a child viewmodel to which textbox is bound to.
Adding a layer of abstraction between parent and child (e.g. events) adds a level of complexity and as a result it should be justified. If the value this indirection provides is higher than the cost of increased complexity of the code (e.g. it's now less clear what happens when command on a parent is executed, you will have to solve a problem how child gets subscribed to parent's event without obtaining the actual reference to it and vice-versa, adding additional dependencies between parent a child will require adding additional events, which pollutes the actual logic with all the plumbing, etc.) then certainly events (or something like PropertyObserver) might be a next logic step.

This seems like an ideal situation for using an EventAggregator like the one in the Composite Application Guidance / Prism.
In this model, you can set up a MessageBus in the root of the application (or other common area).
// in App.xaml.cs
public static IEventAggregator MessageBus = new EventAggregator();
Then set up a common Messages library
// in Messages.cs
public class SimpleCommand: CompositePresentationEvent<SimpleObject> { }
Where SimpleObject is a class or variable that contains all the info necessary to process this event.
// in control with button
App.MessageBus.GetEvent<Messages.SimpleCommand>().Publish(SimpleObject);
// anywhere in your app that you "care" about this
App.MessageBus.GetEvent<Messages.SimpleCommand>().Subscribe(ProcessingMethod);
Where ProcessingMethod is a method that takes a SimpleObject as a parameter.
Then you can spout off messages from anywhere and process them anywhere - across viewmodels, controls, etc. You can even pass MessageBuses between components if you are dynamically loading parts of the app. Works well.

Related

Backbone.js - sharing part of a model with another view

I have a parent view with parent model, and a child view.
I would like to pass a reference to part of the model (a collection) to the child model, so the child model can monitor this for changes and react accordingly.
I'm not sure about the best way to do this - possibly one of these approaches?
Pass whole model : I don't want to do this, as the model contains a
bunch of stuff that the child shouldn't know about.
Pass part of the model : I don't think this is possible... if I use
this.model.get('thesubpart'), I think I will be passing a value, not
a reference.
Bind the child event in the parent view : is this the way to go? I'm
not sure how I would go about doing this.
Your question is a little bit confusing, but I think you want a child model to react to something happening in a parent model, though I'm not sure if the parent is a collection or a single model itself.
The preferred way to do this is through events (i.e. parent.on('change', child.handleParentChange), where handleParentChange is a function defined on the child model. Since you seem to be interested in only a specific attribute change, you could bind to the more specific "change:thesubpart" event.
There are different ways to do this, such as an event aggregator, but the general idea is the same. Be careful of zombies, though. If the parent outlives the child, it will keep the child in memory because of the binding (an advantage of the event aggregator, if implemented correctly).

MVVM pass values between view models

I try to deal with problem of passing value from one ViewModel to another. Here is an example.
We have Parent View and its corresponding ViewModel, in that View we select item and then we want to create new Child View (to edit details of selection) which instantiates its ViewModel in XAML.
Problem occurs when I need to pass value to the Child ViewModel constructor (it is Id of data that has to be fetched from database). I assume Parent's ViewModel has to communicate with Child's ViewModel - but it cannot be done since Child's ViewModel is not instantiated until Child's View do that in XAML, so we cannot use Messenger (MVVM Light Toolkit) and just propagate that info from Parent's ModelView because Child's ModelView has not been able to subscribe (register to that type of messages).
I do not want to break MVVM pattern, and cannot find any good solution for that. I appreciate for all help I can get.
One of the main tenants of the MVVM pattern is that you should be able to execute your ViewModel code without a View, in order to unit test your View logic. In othe words, ideally you should be able to execute your application in a 'headless' mode.
In your example you state that the ParentView creates a ChildView which in turn creates a ChildViewModel (which you are struggling to connect up). Can this work in headless mode? It seems to me that you are relying on your View to perform this Parent-Child navigation.
If you flip it the other way, have ParentViewModel create ChildViewModel, you no longer have a problem with communication between ViewModels. The ParentView needs to 'watch' (i.e. property change) for the new ChildViewModel being creates, and constructs the ChildView accordingly.
In more detail:
ParentView instantiates ParentVM
User interacts in such a way that the child is required
ParentVM creates a ChildVM, exposing it via a ChildVM property
ParentView handles the resultant PropertyChanged event, creating a ChildView, setting its DataContext to ChildVM.
What if any framework are you using? By that, I mean MvvmLight, Caliburn Micro, or Prism. Each framework has a messaging infrastructure. You can harness them to pass state back and forth using a publish/subscribe methodology. For example, take a look at Prism. There are several Quickstarts that show the eventing model. You can also maintain a view controller to orchestrate communication between views.
Take a look at Ward Bell's Prism Explorer sample app. This is an article from '09 however it's still relevant today. Especially see how he passes an entity object from a list view to a child detail view.

Using MVVM in WPF, should I launch child windows from View code behind, or ViewModel?

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.

Silverlight 4: Reliable Commanding with RequerySuggested Functionality?

One of the major problems I have been running into in Silverlight is its lack of robust Commanding support (ala WPF). More specifically, I find it very difficult to apply the MVVM pattern cleanly and with reasonable encapsulation because of the requirement to manually call RaiseCanExecuteChanged() on any property that can affect the state of a Command.
As an example, I have a parent/child View bound to a parent/child ViewModel. The parent View binds to a command on the parent ViewModel. The parent view has multiple child views, each of which is a usercontrol that contains a series of built-in controls (textboxes, comboboxes, etc.), which are bound to the child view model.
The state of the parent command (i.e. whether or not it can execute) is based on the state of each of the child controls. For example, all textboxes for all child usercontrols must have valid values. This requires the properties that these controls bind each call RaiseCanExecuteChanged(), which means they have to have knowledge of either the ICommand itself, or a delegate to call the RaiseCanExecuteChanged() method.
Injecting the command or delegate feels wrong to me, especially in situations more complex than described above, for example when there are 3+ layers of controls, and these references need to be passed all the way down the chain. It's also a bit more housekeeping, since each time a child gets instantiated, an extra step of adding the command or delegate has to be taken.
This would all be made much simpler if Silverlight supported CommandManager.RequerySuggested functionality, like WPF does.
I have seen articles that suggested it was possible to implement RequerySuggested in Silverlight (one such article), but see very little commentary on whether it's reliable and performs adequately.
How have others worked around this limitation with Silverlight?
One method I've used in the past is to use the messaging engine from Laurent Bugnion's MVVM Light framework (http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspx).
In essence, the children send a message to request that the commands be required. The listener, which can sit in the parent, responds to the messages and calls RaiseCanExecuteChanged().
I've found MVVM Light to be worth it just for the messaging engine. Though you do have to be careful and unregister the listener when the parent view is disposed.
Hope that helps.

How would you work with "MDI-ness" in an application that wants to use the MVP pattern?

The situation: MainForm (assigned to the MainPresenter) is up and running. The user click a ShowFoo button - an event is passed to the MainPresenter which in turn creates new FooPresenter and the FooView. How should I proceed now ? Where should the presenter be created and where should the view be created and most importantly, where should the MDIParent property be set ? (so fat I kind of think that should be done in the main view.
Notes: I am using a dependency framework, though that is quite irrelevant to the problem. Ideally I would like the IView to independent of the Form class.
The way I would handle it have a function off of the MainPresenter interface that allows me to create a FooPresenter (as well as a Foo2Presenter, etc). THe MainPresenter has all the information inside of it to properly setup a child form of the MDI parent. Hence why it makes sense to have it there.
An alternative is to have a AppPresenters class that has the MainPresenter and the FooPresenter as properties or functions. Here the AppPresenters hold the presenter classes as well takes on the responsibility for tying the forms together to have a proper MDI application. The implication of this approach is the fact the application is a master/parent form with a bunch of child forms is not reflected in the design of your interfaces.
The differences between the two approaches is minimal in my opinion. Both could be adapted to a different style of UI readily. So go which on makes better sense for you and your application.

Resources