Keep using same View/ViewModel instances

May 8, 2012 at 9:47 PM


I am developing an application that has a main view and support view and corresponding VM for each. The main view has a list of items that are presented in a RichTextBox with links. When the user click on a link I want to show it in a supporting document that should be shown in the support view.

The initialization of the support view can take a little while as it parse the support file which can be big and thus, preparing the FlowDocument will be a while.

Once the VM is initialized, I use the IUIVisualizationService to find the corresponding view and show it.

Since the main VM knows the support VM (it is a local variable) I can have the navigation command in the support VM and the click command of a link in the main VM just execute the command on the support VM (_supportVm.CommandNavigate.Execute())

My idea here was to reuse the VM and the View until the user changes the support file and thus not have to create/match it each time. I guess I can do the time consuming processing in the main VM but still I would not like to create the support VM and View each time.

The problem is that with the way mentioned above it is not working. I guess the IUIVisualizationService does not reuse views (why should it) and there is some default behavior on the view that resets it's DataContext(VM). Currently what I am having is:

1) If the user closes the support view, I assume that it resets the VMs (DataContext) commands because the next time I come to call on the VM the CommandNavigate is null.

2) If the user does not closes the support view, I don't really have a way to show it again. If I try to show the VM using the IUIVisualizationService I get an error because the FlowDocument is still linked to the old support view.

How should I go about implementing something like that - is there a way to just hide the view and keep showing/hiding it?

Another small concern - I am using the IPleaseWaitService to show a message to the user when loading the support file. When loading is done I call Hide() and then IUIVisualizationService.Show on the support view - this sequence of action for some reason pops the main view to the front... Is this normal? What I should do so that the support view is the one with the focus?



May 9, 2012 at 6:43 PM

Yes, the IUIVisualizer indeed does not re-use views, it creates a new one every time. The biggest concern is that the view model is also closed, which makes it harder for Catel to re-use it. It is possible to no close view models inside a user control, but not in a window (why would you? closing a window is closing a VM).

There is a small hack which you can use. I consider the MessageMediator for solving such issues is an anti-pattern, but since all other MVVM frameworks seem to get a way with it, here is what you can do:

1) Register a message in the message mediator, and set the created popup window as receiver

2) If the user clicks the command, show the window by sending a message (which the window will receive)

3) When the user closes, don't actually close, but hide the window. Then the next time step 2 happens, you can simply show it again (and re-use both the window AND the view model)

The MessageMediator is located in the Catel.Messenging namespace, you can find the docs here.

The issue with the IPleaseWaitService is that it needs a parent window, and uses the main application window for this. We currently have an issue for the message boxes as well, so we are looking into it.