J. H.
J. H.

Reputation: 111

uwp app with multiple windows on Win10: how to bring a specific window to the front

I tried Window.Activate(), but that does not appear to bring up the specific window, just the app itself.

I have multiple windows that the app is managing, and I want to be able to bring up a specific window on demand.

Upvotes: 1

Views: 647

Answers (1)

iam.Carrot
iam.Carrot

Reputation: 5276

I am sorry for overshooting the two hours with 2 days but as promised below is your solution. It might not be the ideal way of achieving such a functionality but in my opinion it's a solution that works perfectly. I've uploaded a solution as well to one drive.


The Solution:

To actually handle multiple window switching without relaunching a new window rather in your words:

bring up a specific window on demand.

What you need is a window logging service. What this service would do is, each time it opens up a new window, it logs it along with the type of window opened. I've kept a neat enum to manage the windows that open.

I'll talk more about the window logging service more than the UI part as the UI is just basic buttons calling the service.

The Window Service:

  1. Make a singleton instance of the windowLauncherService
  2. Maintain a private dictionary of WindowIDs and TypeOfWindow launched.
  3. On call of the HandleWindowSwitch method, check if the window has already been launched (check if it exists in the private Dictionary), if it does simply call await ApplicationViewSwitcher.TryShowAsStandaloneAsync(Convert.ToInt32(existingViewID));. Where you get the existingViewID from the key of the dictionary.
  4. If the window has not been launched before, then simply launch the window and then log it.

That's it. Below is my WindowServiceCode:

namespace MultipleWindowTracker.Services
{
internal class WindowLauncherService
{
    public static WindowLauncherService Instance { get; } = new WindowLauncherService();

    private Dictionary<int, WindowType> WindowLogs { get; set; }

    internal async void HandleWindowSwitch(WindowType typeOfWindow)
    {
        if (WindowLogs?.ContainsValue(typeOfWindow) == true)
        {

            var existingViewID = WindowLogs?.FirstOrDefault(x => x.Value == typeOfWindow).Key;
            if (existingViewID != null)
            {
                await ApplicationViewSwitcher.TryShowAsStandaloneAsync(Convert.ToInt32(existingViewID));
            }
            else
            {
                //Handle Error Here!
            }
        }
        else
        {
            await OpenNewWindow(typeOfWindow);
        }
    }


    /// <summary>
    /// Logs the new window.
    /// </summary>
    /// <param name="WindowID">The window identifier.</param>
    /// <param name="typeOfWindow">The type of window.</param>
    private void LogNewWindow(int WindowID, WindowType typeOfWindow)
    {
        if (WindowLogs?.ContainsKey(WindowID) == true)
            return;

        if (WindowLogs == null)
            WindowLogs = new Dictionary<int, WindowType>();

        WindowLogs.Add(WindowID, typeOfWindow);
    }


    /// <summary>
    /// Opens the new window and if success logs it.
    /// </summary>
    /// <param name="typeOfWindow">The type of window.</param>
    /// <returns></returns>
    private async Task OpenNewWindow(WindowType typeOfWindow)
    {
        Type windowToLaunch = null;
        switch (typeOfWindow)
        {
            case WindowType.Main:
                windowToLaunch = typeof(MainPage);
                break;
            case WindowType.First:
                windowToLaunch = typeof(Scenarios.FirstWindow);
                break;
            case WindowType.Second:
                windowToLaunch = typeof(Scenarios.SecondWindow);
                break;
            case WindowType.Third:
                windowToLaunch = typeof(Scenarios.ThridWindow);
                break;
            default:
                return;
        }



        CoreApplicationView newView = CoreApplication.CreateNewView();

        var currentFrame = Window.Current.Content as Frame;
        if (currentFrame.Content is MainPage)
        {
            var mainFrameID = ApplicationView.GetForCurrentView().Id;
            LogNewWindow(mainFrameID, WindowType.Main);
        }

        int newViewId = 0;
        await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            Frame frame = new Frame();
            frame.Navigate(windowToLaunch, null);
            Window.Current.Content = frame;
            // You have to activate the window in order to show it later.
            Window.Current.Activate();

            newViewId = ApplicationView.GetForCurrentView().Id;
        });
        bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
        if (viewShown)
        {
            LogNewWindow(newViewId, typeOfWindow);
        }
        else
        {
            //handle error on launch here!
        }
    }

}

public enum WindowType
{
    Main,
    First,
    Second,
    Third
}
}

And on button click this is what you do:

private void HandleWindowChange(object sender, RoutedEventArgs e)
    {
        var s = sender as Button;
        var conversionSuccessful = Enum.TryParse((string)s.Tag, true, out Services.WindowType TypeOfWindow);
        if (conversionSuccessful)
        {
            Services.WindowLauncherService.Instance.HandleWindowSwitch(TypeOfWindow);
        }
    }

Please Note: All Buttons in all views have the same click event code and they all call the same singleton instance.


Refer to my source code from one drive. For any help do let me know in the comments section. Please note I am using VS2017, if you're using older versions, few things might not be available for eg: the out keyword in Enum.TryParse<> The Link to the complete solution on github

Upvotes: 1

Related Questions