【问题标题】:uwp app with multiple windows on Win10: how to bring a specific window to the frontWin10上具有多个窗口的uwp应用程序:如何将特定窗口置于最前面
【发布时间】:2018-01-25 16:00:26
【问题描述】:

我尝试了 Window.Activate(),但这似乎并没有调出特定的窗口,只是应用程序本身。

我有多个应用程序正在管理的窗口,我希望能够按需调出特定窗口。

【问题讨论】:

标签: uwp windows-10-universal


【解决方案1】:

我很抱歉在 2 天内超过了两个小时,但如下承诺是您的解决方案。它可能不是实现这种功能的理想方式,但在我看来,它是一个完美运行的解决方案。我也将解决方案上传到一个驱动器。


解决方案:

实际处理多个窗口切换而不重新启动一个新窗口,而不是用你的话:

按需打开特定窗口。

您需要的是一个窗口日志记录服务。该服务所做的是,每次打开一个新窗口时,它都会将其与打开的窗口类型一起记录下来。我保留了一个整洁的enum 来管理打开的窗口。

我将更多地谈论窗口日志服务而不是 UI 部分,因为 UI 只是调用该服务的基本按钮。

窗口服务:

  1. 创建windowLauncherService 的单例实例
  2. 维护私人字典WindowIDsTypeOfWindow 已启动。
  3. 在调用HandleWindowSwitch 方法时,检查窗口是否已经启动(检查它是否存在于私有字典中),如果它只是调用await ApplicationViewSwitcher.TryShowAsStandaloneAsync(Convert.ToInt32(existingViewID));。从字典的键中获取现有视图ID。
  4. 如果之前没有启动过该窗口,则只需启动该窗口并记录它。

就是这样。下面是我的 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
}
}

点击按钮时,你会这样做:

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);
        }
    }

请注意:所有视图中的所有按钮都具有相同的点击事件代码,并且它们都调用相同的单例实例。


从一个驱动器参考我的源代码。如需任何帮助,请在 cmets 部分告诉我。 请注意 我使用的是 VS2017,如果您使用的是旧版本,则可能有一些东西不可用,例如:Enum.TryParse&lt;&gt; 中的 out 关键字 The Link to the complete solution on github

【讨论】:

  • 啊,所以您使用的是 ApplicationViewSwitcher...嗯。明天让我试试,我会告诉你的。不错的解决方案,顺便说一句。谢谢
  • 是的,这是唯一的切换方式。除非有另一种我猜不存在的方式,否则人们会回答这个问题。请让我知道结果。 onedrive 上也上传了一个示例解决方案
  • @J.H.这个问题已经解决了吗?如果是,您能否将我的答案标记为正确(如果您喜欢这种方法,甚至可以投票),以便关闭该线程?
  • 我是最差的。非常抱歉。完全被这个问题边缘化了。应该能够在月底之前回到这个...啊现在的紧迫性;-)
  • 所以,终于有时间测试了。包装器上的工作令人印象深刻,但结果仍然是......什么都没有。 TryShowAsStandaloneAsync 根本不会将子窗口带到前面...我确定实际的应用程序已拉起,但由于我与之交互,它已经在前面...我正在寻找的是一种方式弹出子窗口...
猜你喜欢
  • 2020-01-16
  • 2011-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-28
  • 2017-12-02
  • 1970-01-01
  • 2022-09-23
相关资源
最近更新 更多