There is an unsaved comment in progress. You will lose your changes if you continue. Are you sure you want to reopen the work item?
An MVVM-friendly way for opening and closing a child window from a view model, and sending data back and forth between the two corresponding view models.
I have a child window with a view model. The view model has some dependencies that should be injected (I'm using unity). I want to trigger opening this child window from another view model. I want to pass some data to the child window's viewmodel and on closing the child window I want some data back.
It turns out there isn't a ready-to-use solution for this. I prefer to follow the InteractionRequest approach of Prism, and I like the idea of passing context data. I don't like the option of communicating data between the calling view model and the child window's view model using the event aggregator, because in principle any party can subscribe to these events, while the data passing should be private between both view models. Furthermore, the InteractionRequest approach supports a callback mechanism where the context data is returned to the calling view model, with the event aggregator approach this would mean sending yet another event.
Therefore, after quite some experimenting and searching, I ended up with the following approach which I found pretty satisfying:
1) First, to have proper dependency injection in my view models, I obtain an instance of the view model in the constructor of the child window using ServiceLocator.Current.GetInstance. This is perhaps not the nicest way, but it works.
2) Second, I make use of Prism's InteractionRequestTrigger in combination with a custom PopupChildWindow action to open my child window and to pass context data to the view model of the ChildWindow. The child window's view model implements IInteractionRequestDataReceiver. My calling view model calls Raise on an InteractionRequest object and passes an instance of InteractionRequestData as context data. InteractionRequestData is a class that inherits from Notification (this is a requirement of Prism) and forms the data object to pass to the child windows's view model. This is a strongly-typed way of passing data between view models using the InteractionRequest approach. There is no coupling between the view models (apart from the commonly shared InteractionRequestData type, which can be seen as a sort of contract between the two view models). Apart from the parent view, that defines an interaction trigger for, there's no knowledge in the views of the data transfer that takes place.
3) Third, I created an ICloseRequest interface and a CloseRequestor attached property for child windows. My child window's view model implements ICloseRequest, the ChildWindow creates a binding for the CloseRequestor property. The effect is that the view model can raise a Close request, which is then responded to by the child window by closing itself. This is a simple MVVM way for closing a child window from within a view model.
These three things together form a pretty nice MVVM way for firing an interaction request, handling the request in a child window, sending some input data to the child window's view model, closing the child window, and sending back result data to the calling view model. It extends Prism's interaction request pattern by passing the context data not to the child window's data context, but to the view model of the child model (if it implements the IInteractionRequestDataReceiver interface ).
I've attached an example program that makes use of this new meachnism. I hope you like it.