Closing child windows when shell closes

Topics: Getting Started
Oct 16, 2013 at 2:15 PM

I would like to know which is the right/way to auto close children when my shell window has been closed. In my application I've a child window, which I opened via the window manager. If I close the shell window, the child window and the application remains active until I close the child window. How can I change this?
Oct 16, 2013 at 2:40 PM
If you set the child window as a true child of the shell view (setting the Parent property), it should close automatically.
Alternatively, you can modify the application ShutdownMode, if you just want to close the application whenever the main window closes, regardless of children.
Oct 17, 2013 at 8:19 AM

thanks for your advice. Yesterday I spent some time on studying the documentation about screens and conductors whiche exactly covers my requirements. I'm really excited about those features in caliburn.micro. Even complex scenarios are possible with less effort. It's really worth reading the documentation about the screens and conductors.
Oct 17, 2013 at 9:54 AM
Hmm, but I dont know why the OnDeactivate-Method of the shell isn't being called when I close the shell window? Each other window calls that methode but not the sell? The viewmodel for my shell window is derived from AllActiveConductor. What is the recommenden Method/strategy to close the child windows?
Now I placed the code in the CanClose-Method which seems a little bit hacky for me:
public override void CanClose(Action<bool> callback)
    var activeChildren = GetChildren().Where(c => c.IsActive).ToList();
    foreach (var view in activeChildren)
        DeactivateItem(view, true);
Oct 17, 2013 at 10:06 AM
Conductors tipically handle this scenario for you. In the specific case, as long as the Conductor is deactivated, all child items are deactivated/closed too. You can check Conductor source code to be sure.

Now, the issue here is that conductor's Deactivate method is not called, which means that either the conductor was never activated in the first place, or the view is not properly notifying the view-model.

The default WindowManager implementation (and specifically, the WindowConductor class defined internally), should take care of everything: it activates the view-model during the ShowWindow call (specifically, as soon as the WindowConductor is created), links the Closing/Closed event from view, link Deactivated event from view-model, and keeps both view and view-model in sync.

So, the default implementation should behave properly, which means that I need to assume that there is something fishy with your code: what kind of view are you using as a main window? How do you activate your main view-model? Are you sure the conductor is activated when the window is displayed? Can you post a bit of code, regarding the Bootstrapper (and specifically the part where the main view-model is created)?
Oct 17, 2013 at 11:50 AM
Edited Oct 17, 2013 at 12:14 PM
So I thought it was intended that the conductor takes care of it after reading the documentation. I also thing thats a bug (or fish) in my source, maybe something from older versions of caliburn.micro (I started with V1.0).

Now here is a part of the bootstrapper code, it only contains the most relevant parts - alot of lines I've dropped cause its a few hundred already.
internal sealed class Bootstrapper : Caliburn.Micro.Bootstrapper<IShell>
    protected override void StartRuntime()

    protected override void Configure()

        IocProxy.HasInstance      = HasInstance;
        IocProxy.GetInstance      = GetInstance;
        IocProxy.InjectProperties = BuildUp;


    protected override void OnStartup(object sender, StartupEventArgs e)
        base.OnStartup(sender, e);
The implementation of the ShellViewModel is in an extra assembly, which is loaded by using MEF. There's a class where the interface is assigned to the implementation using LightCore as a DI Container:
public class MyModule : Domain.Core.MyModule
        public override void OnConfigureContainer(IServiceContainerAdapter adapter)
            adapter.Register<IShell, ShellViewModel>(true);
            adapter.Register<IChapterIndexInfoView, ChapterIndexInfoViewModel>(true);
            adapter.Register<IDrawingsView, DrawingsViewModel>(true);
I'm using an adapter to be independent from any container implementations. The boolean-flag is used to become the object as single instance, which is the case for the ShellViewModel.

This here is the interface of the ShellViewModel:
public interface IShell : INotifyPropertyChanged, IDeactivate
Ofcause it has some methods and properties which I dropped, to make things cleaner. In the ShellViewModel-class I've no special code for initalization conductors or anything else. It has this class definition:
internal partial class ShellViewModel : AllActiveConductor<IScreen>, IShell
The AllActiveConductor is just a derived class from Conductor<T>.Collection.AllActive and it contains only Helper-Methods for assigning values to properties.

Currently I've overriden the OnViewAttached-Method, to make it work but I guess that should be done by CM and I'm not sure what else isn't initialized correclty or not working as intended.
protected override void OnViewAttached(object view, object context)
    base.OnViewAttached(view, context);
    var window = view as Window;
    if (window != null && window.GetType() == typeof(ShellView))
        window.Closing += (s, e) => OnDeactivate(true);
Oct 17, 2013 at 12:31 PM
Could you check if the IShell is actually activated once the view is displayed?
The only thing that comes into my mind, is that an improper type check prevents the IShell instance to be recognized as an IActivate. What if you explicitly define the IShell as IActivate?
Oct 17, 2013 at 12:43 PM
Edited Oct 17, 2013 at 12:45 PM
The OnActivate-Method is beeing called and from the callstack I see that this is done from the WindowConductor.
Besides that in my hack in the OnViewAttached-Method, I had to use the window.Closing event. First I used the window.Closed event but then the application closes before the method has been called. Maybe there is a generally timing problem with the conductor? Don't know which event the conductor is using, just an idea.
Oct 17, 2013 at 1:07 PM
If the OnActivate is called, it means that the WindowConductor is actually being used. So, you need to determine:
  1. If the Closed/Closing events are properly attached (without pdbs it can be quite tricky, since you need to inspect the Window instance and check if the Closed/Closing events have at least an handler attached. Try to use the IViewAware interface to retrieve the Window instance).
  2. What happens changing the application ShutdownMode to OnLastWindowClose or OnExplicitShutdown.
I find quite disturbing the fact that the application exits before the Closed event is called (this is not the normal behavior in WPF, what platform are you targeting?). Normally, the application shutdown happens after the main Window is closed (if the ShutdownMode is set to on MainWindowClose). This kind of behavior should be expected just in case the Closed event calls an async method which is not awaited... but it does not seem to be your case...
Oct 18, 2013 at 8:30 AM
Ok, I got it now. It was all my fault and it was really fishy. After some research and changes to the window I ended up with this lines of code from the code behind of the window:
protected override void OnClosed(System.EventArgs e)
    if (_shell != null)
That makes clear why the Closed-Event has never been triggered for this window.
Thanks for your help and patience, after correcting the code the even fires and the OnDeactive method is beeing called in the viewmodel.
Oct 25, 2013 at 12:21 PM
Finally after my last post and fixing that bug, I still have some questions about the conductors and windows. What is now the recommended way or best practive to open a new window?? Since reading the documentary about the conductor I was opening it by using the window manage from caliburn.micro. Mostly I've used a command for it that do the following:
So what can I do to use the condutor of the shell is getting acknoledge of the new window? How is the relationship between the windows/conductors??
Oct 28, 2013 at 12:59 PM
To open a new window, you just use the IWindowManager, as you are doing.
Regarding aknowledgement of child windows, or related windows, you need to think in terms of related view-models. The main conductor can be totally unaware of the fact that part of its children are tabs, dialogs, or whatever, it just needs to know if children are present, and be able to activate/deactivate them.

This means that the main shell view-model must be a custom conductor, that internally uses IWindowManager.ShowDialog whenever needed, keeping track of its children.
Marked as answer by Tactive on 10/28/2013 at 8:50 AM
Oct 28, 2013 at 4:55 PM
Edited Oct 28, 2013 at 5:13 PM
Thanks (again) for your explanation, that's what I got in mind after investigating the source of caliburn and now I'm quite confident to have a good solution for my project.

I derived from Caliburn's window manager and used the settings parameter. So I can now create a relationship from anywhere by using this line of code:
IocProxy.Get<IWindowManager>().ShowWindow(MyViewModel, settings: new ScreenOwner(MyShell).MakeWMSettings());