我很抱歉在 2 天内超过了两个小时,但如下承诺是您的解决方案。它可能不是实现这种功能的理想方式,但在我看来,它是一个完美运行的解决方案。我也将解决方案上传到一个驱动器。
解决方案:
实际处理多个窗口切换而不重新启动一个新窗口,而不是用你的话:
按需打开特定窗口。
您需要的是一个窗口日志记录服务。该服务所做的是,每次打开一个新窗口时,它都会将其与打开的窗口类型一起记录下来。我保留了一个整洁的enum 来管理打开的窗口。
我将更多地谈论窗口日志服务而不是 UI 部分,因为 UI 只是调用该服务的基本按钮。
窗口服务:
- 创建
windowLauncherService 的单例实例
- 维护私人字典
WindowIDs 和TypeOfWindow 已启动。
- 在调用
HandleWindowSwitch 方法时,检查窗口是否已经启动(检查它是否存在于私有字典中),如果它只是调用await ApplicationViewSwitcher.TryShowAsStandaloneAsync(Convert.ToInt32(existingViewID));。从字典的键中获取现有视图ID。
- 如果之前没有启动过该窗口,则只需启动该窗口并记录它。
就是这样。下面是我的 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<> 中的 out 关键字
The Link to the complete solution on github