I am working on an app using Caliburn.Micro. I need to open a set of identical windows on multiple monitors at once, and I cannot figure out how to do this cleanly.
My idea is this:
ChildViewModel
/ ChildView
contains the things I need to show on multiple screens.ParentViewModel
inheriting from ConductorBase<ChildViewModel>
.ParentViewModel
is created, it creates the required number of ChildViewModel
and uses WindowManager.ShowWindow
to show each of them.WindowManager
implementation takes care of placing these views where they are supposed to be.All of the above works, with one exception: the ParentView
is displayed in its own window. How can I avoid this happening? what would be the canonical way of doing what I am trying to do?
What I want to do is conduct multiple windows from a single conductor, without the conductor itself showing a window.
What about this schema?
SystemTrayVM
(VM for your notification area, its View is the sys tray icon)
|
|
MultipleDesktopManager
(not a VM, not a ConductorBase, no View, not visible)
|
.-------------------|------------------.
| | |
| | |
SingleDesktopVM SingleDesktopVM SingleDesktopVM
(its View holds child views. If necessary, it can be a ConductorBase)
|
.-------------|------------.------ - - - .
| | |
| | |
SideBarChildVM MainChildVM FooterChildVM
SystemTrayVM is responsible for all interaction made available through the notification area (right click menu action, etc.). It would not actually open/close the windows visible to user, but rather forward those commands to the MultipleDesktopManager.
MultipleDesktopManager is not visible and is not a VM. Its responsibility is to e.g. open/close all single desktop parent windows when needed. Being completely separate windows, there should be no need for a full blown conductor. From my experience, it is enough to provide it with an IWindowManager so that it can actually show/close the single desktop parent windows. Maybe it could also activate/deactivate them, but no need to keep track of a current active item or things like that.
In a recent past we faced & solved the issue of a WPF application starting not visible, only found in system tray, and from there being able to show/hide the actual main application window.
In that scenario, we offloaded the task of hiding/showing the main app window to a helper class (not a VM) invoked by the SystemTrayVM. That would be the equivalent of MultipleDesktopManager in this schema.
Regarding the WPF application starting from system tray only, we put together a PoC on GitHub that shows how to completely integrate this WPF NotifyIcon control with a Caliburn.Micro ViewModel-first approach and DI through Autofac.
EDIT: The rationale is that Conductor implementations offered off the shelf by CM seem more adequate for a window holding other child windows. If the holder is not itself visible, maybe those conductor implementations are not the perfect choice. As you said in comments, it's like needing a Conductor not being also a Screen. There's an interesting bit on CM composition doc page about "Quasi-Conductors". In the end, the MultipleDesktopManager idea is basically that of a simple conductor that manages many windows, without implementing the IConductor interface but still using the WindowManager in order to process SingleDesktopVMs lifecycle correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With