2

I would like to update from 6.3 to 7.

I seem to have hit a road block.

When using the PrismApplication class in the App.xaml, CreateShell expects a return type of Window instead of the previous BootStrapper which wanted a DependencyObject.

My MainShell is a modified Telerik RadWindow which itself is a modified System.Windows.Controls.HeaderedContentControl and casting to Window is not possible.

Is there a way around this so I can use the PrismApplication object or do I have to roll back and use the BootStrapper like before?

Lance
  • 251
  • 5
  • 13

2 Answers2

4

do I have to roll back and use the BootStrapper like before?

The bootstrapper is still there. It is marked as deprecated and might go away in a future version, but as long as it's there, you can use it. At least, until the problem with PrismApplicationBase is fixed. You should create an issue on github for that.

Edit:

The issue has already been brought up and it won't be fixed (1413).

I'll copy the proposed workaround from the issue for reference:

protected override Window CreateShell()
{
    return null;
}

protected override void OnInitialized()
{
    var shellWindow = Container.Resolve<ShellWindow>();
    shellWindow.Show();
    MainWindow = shellWindow.ParentOfType<Window>();

    // there lines was not executed because of null Shell - so must duplicate here. Originally called from PrismApplicationBase.Initialize
    RegionManager.SetRegionManager(MainWindow, Container.Resolve<IRegionManager>());
    RegionManager.UpdateRegions();
    InitializeModules();

    base.OnInitialized();
}
Haukinger
  • 10,420
  • 2
  • 15
  • 28
  • Annoying the issue has been locked as an alternative use case would be an application that is ran in the system tray from start so would have no starting window! – metoyou Feb 20 '20 at 10:28
0

In order to make App.xaml.cs more like a normal one and to save time, the following class was created. Note that this class uses System.Reflection. It was created by referring to the implementation of PrismApplicationBase, helped by Haukinger's answer.

/// <summary>
/// <br>Make sure that <see cref="Application.MainWindow"/> always returns null. Use <see cref="MainElement"/> instead.</br>
/// <br>Make sure that <see cref="CreateShell"/> is sealed. Use <see cref="CreateElement"/> instead.</br>
/// </summary>
public abstract class GeneralizedPrismApplication : PrismApplication
{
    protected sealed override Window CreateShell()
    {
        return null;
    }

    /// <summary>
    /// Creates the shell or main element of the application. Use this method instead of <see cref="CreateShell"/>.
    /// </summary>
    /// <returns>The shell of the application.</returns>
    protected abstract FrameworkElement CreateElement();

    /// <summary>
    /// Gets or sets the main element of the application. Use this property instead of <see cref="Application.MainWindow"/>.
    /// </summary>
    public FrameworkElement MainElement { get; protected set; }

    protected override void Initialize()
    {
        base.Initialize();
        var shell = CreateElement();
        if (shell != null)
        {
            var method = typeof(MvvmHelpers).GetMethod("AutowireViewModel", BindingFlags.Static | BindingFlags.NonPublic);
            method.Invoke(null, new object[] { shell });
            RegionManager.SetRegionManager(shell, this.Container.Resolve<IRegionManager>());
            RegionManager.UpdateRegions();
            InitializeShell(shell);
        }
        
    }

    /// <summary>
    /// Initializes the shell.
    /// </summary>
    /// <param name="shell"></param>
    protected virtual void InitializeShell(FrameworkElement shell)
    {
        MainElement = shell;
    }

    /// <summary>
    /// Do not override this method. Use <see cref="InitializeShell"/> instead.
    /// </summary>
    /// <param name="shell"></param>
    protected sealed override void InitializeShell(Window shell)
    {
        ;//Originally MainWindow = shell;
    }

    /// <summary>
    /// Contains actions that should occur last.
    /// </summary>
    protected new virtual void OnInitialized()
    {
        ;//Originally MainWindow.Show();
    }

    protected override void OnStartup(StartupEventArgs e)
    {
        this.ShutdownMode = ShutdownMode.OnExplicitShutdown;//Without this, the application will exit.
        base.OnStartup(e);
    }
}

This problem can be solved by simply

  1. Making App inherit this class in App.xaml
  2. Replacing MainWindow with MainElement and CreateShell() with CreateElement() in App.xaml.cs.
mikm
  • 111
  • 1
  • 4