How is it possible to re-use and compose parts in CM managed windows? I have found posts regarding using two UserControls to bind to the same ViewModel, but not so much if I want to have multiple views and viewmodels all composed in the same window. (a viewmodel for each view composed into a "master view")
The first part of my question would be how to break up components for re-use? If I have two areas of a window where one is a datagrid and another is a details view with labels and text boxes should these be in separate usercontrols, customcontrols or windows? Each one would ideally be stand alone so they can be separated and used in other windows.
So I would end up with 2 viewmodels and 2 views if they were separated. Now lets say I would like to create 3 windows, one window with the first view, the second with the second view and a third with both views. How do I use CM to create the window for each and wire up each view to their viewmodel? From the examples I have seen I see for the most part a single view and viewmodel in a window.
I'm not going to claim to be an expert in CM by any means, but I've had reasonable success with a simple "benchmark explorer" I've been writing. That uses a single "shell view" that composes two other views, each with its own ViewModel. The shell view looks like this:
then
ResultsGraphView
andBenchmarkPickerView
are each like this:The
ShellViewModel
exposes the other two ViewModels as properties. Those are then passed to the views automatically on construction. (The bootstrapper doesn't provide any way of getting them.)Now this doesn't quite fit your description, because I don't think you could use the two individual views individually as windows - I suspect you would end up with 5 views in total:
I don't think there's a way of getting around the fact that you don't want one
Window
within another, and the top level window has to be... well, aWindow
.Hope this helps, and let me know if you want more details of the small project where I'm doing this - it's far from production quality, particularly in terms of DI, but it may be enough to help you get going.
I think I've previously done something similar to what you're asking. I'd been playing around with one of the
TabControl
with the intention of hosting several different tools for a game I enjoy playing.The main tool is an item browser similar to the usual file explorer type programs, and similar to what Jon has described above. I'll explain some of the parts which may be of interest/relevance (I've removed some of the slightly obscure naming).
The main
ExplorerView
tab is essentially exactly the same the one Jon describes (which is hopefully a good sign - means I'm not crazy =D)The associated
ViewModel
holds two otherViewModels
, used for composing the main explorer view:The
ItemsExplorer
hosts aTreeView
style control, allowing users to explore various categories ofItem
from the game. This is used in multiple places in the application, and is composed into a few different controls.The
ExplorerPanelView
is a panel on the right hand side, that changes to display a number ofViewModels
, based on what type of item the user is viewing. The user also have the option to toggle a few differentViews
over theViewModel
displayed in theExplorerPanelView
.The
ExplorerPanelView
looks like:And the
ExplorerPanelViewModel
behind:I've tried to remove a lot of non-relevant code. Essentially I'm again hosting multiple
ViewModels
as properties (although you could hold a collection) and activating the relevantViewModel
when an approriate event is raised by myItemsExplorerViewModel
. I'm using theCaliburn.Micro
EventAggregator
to handle communication between multipleViewModels
.In theory you could dispense with the properties, and just activate the
ViewModels
referenced in the events themselves.Regarding the
cal:View.Context
andcal:View.Model
- I'm using these all the user to toggle different availableView
states available (eachViewModel
displayed in that panel inherits from a baseViewModel
class which all have aState
property).There are a few places where I pop up different windows using some of the same
Views
andViewModels
. To achieve this, I make use of theCaliburn.Micro
WindowManager
. There isn't a great deal about it in the official documentation (you're best off searching Google and the CM discussions), it pretty does what is says on the tin.If you have a look at the
Caliburn.Micro.IWindowManager
interface you'll see some handy methods that you can call from aWindowManager
instance.So to pop up a new
Window
with aViewModel
of your choice, I did something along these lines:Caliburn.Micro
should again, resolve yourViews
to the correctViewModels
.Hopefully there's something useful in there somewhere. I sort of arrived at this solution through a few design iterations, so this may not be the optimal approach to some of these problems. If anyone has any constructive criticism, please let me know =D