0

I have a ShellViewModel that is a conductor. It has a series of menu items that open various view/viewmodels that are "hosted" in a tab control, similar to the Simple MDI example found here Caliburn Micro Composition Documentation Some of the view items should not be hosted inside the tab control, but rather need to be Non modal windows. I'm able to open them using the WindowManager's ShowWindow method.

However, when these windows lose focus, they remain "on top" of the shell window.

ShellView.xaml

<Window x:Class="SimpleCaliburnWpf.ShellView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:SimpleCaliburnWpf"
    mc:Ignorable="d"
    Title="ShellView" Height="300" Width="300">
<Grid>
    <Button Name="OpenWindow">Open A New Window!</Button>
</Grid>

ShellViewModel.cs

public class ShellViewModel : Conductor<IScreen>.Collection.AllActive
{
    private IWindowManager _windowManager;
    public ShellViewModel(IWindowManager windowManager)
    {
        _windowManager = windowManager;
    }

    public void OpenWindow()
    {
        var vm = new FirstViewModel();
        _windowManager.ShowWindow(vm);
    }
}

FirstViewModel.cs

public class FirstViewModel : Screen { }

Could someone offer suggestions as to how these windows could live behind the shell if the shell is clicked on.

As you can see, ShellView is activated, but FirstView remains in front.

mm8
  • 163,881
  • 10
  • 57
  • 88
priehl
  • 644
  • 2
  • 9
  • 21

1 Answers1

2

You could create a custom WindowManager class that sets the Owner property of the created window to null:

public class CustomWindowManager : WindowManager
{
    protected override Window CreateWindow(object rootModel, bool isDialog, object context, IDictionary<string, object> settings)
    {
        Window window = base.CreateWindow(rootModel, isDialog, context, settings);
        window.Owner = null;
        window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
        return window;
    }
}

Don't forget to register the manager in your bootstrapper:

protected override void Configure()
{
    ...
    _container.Singleton<IWindowManager, CustomWindowManager>();
}

I would like to close these windows when the shell closes, but now that it doesn't own them, this is difficult. Any suggestions here?

You could handle the Closed event of the owner window:

protected override Window CreateWindow(object rootModel, bool isDialog, object context, IDictionary<string, object> settings)
{
    Window window = base.CreateWindow(rootModel, isDialog, context, settings);
    Window ownerWindow = window.Owner;
    window.Owner = null;
    window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
    if (ownerWindow != null)
        ownerWindow.Closed += (s, e) => window.Close();
    return window;
}
mm8
  • 163,881
  • 10
  • 57
  • 88
  • I would like to close these windows when the shell closes, but now that it doesn't own them, this is difficult. Any suggestions here? – priehl Feb 07 '18 at 16:38
  • My view models hold state, and they ask whether they'd like to discard this state within my override of CanClose(). Can a false result from CanClose callback prevent the closing of the shell? – priehl Feb 07 '18 at 17:09
  • I believe your original question has already been answered. Please accept the answer and then ask another question if you have another issue. Please don't ask additional questions in the comments field. – mm8 Feb 07 '18 at 17:40