【发布时间】:2020-07-08 18:43:46
【问题描述】:
我正在编写一个应用程序,它应该能够运行多个视图以在各自的窗口中编辑不同的文档。我写了一些有效的代码,但是我遇到了一些问题。我编写的代码基于 Microsoft (https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/MultipleViews) 提供的多视图示例。
我主要有两个问题。第一个是如果我关闭主视图,即应用程序启动时打开的第一个窗口,然后我无法通过单击应用程序磁贴或打开关联的文件类型来打开任何新视图/窗口,直到我关闭所有视图/窗口并重新启动应用程序。第二个是,当我尝试从 MainPage.xaml.cs 打开一个新视图/窗口时,应用程序崩溃了。
我用来管理 App.xaml.cs 中的视图的代码如下:
sealed partial class App : Application
{
//I use this boolean to determine if the application has already been launched once
private bool alreadyLaunched = false;
public ObservableCollection<ViewLifetimeControl> SecondaryViews = new ObservableCollection<ViewLifetimeControl>();
private CoreDispatcher mainDispatcher;
public CoreDispatcher MainDispatcher
{
get
{
return mainDispatcher;
}
}
private int mainViewId;
public int MainViewId
{
get
{
return mainViewId;
}
}
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
protected override async void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
alreadyLaunched = true;
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
else if(alreadyLaunched)
{
var selectedView = await createMainPageAsync();
if (null != selectedView)
{
selectedView.StartViewInUse();
var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(
selectedView.Id,
ViewSizePreference.Default,
ApplicationView.GetForCurrentView().Id,
ViewSizePreference.Default
);
await selectedView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
var currentPage = (MainPage)((Frame)Window.Current.Content).Content;
Window.Current.Activate();
});
selectedView.StopViewInUse();
}
}
// Ensure the current window is active
Window.Current.Activate();
}
protected override async void OnFileActivated(FileActivatedEventArgs args)
{
base.OnFileActivated(args);
if (alreadyLaunched)
{
//Frame rootFrame = Window.Current.Content as Frame;
//((MainPage)rootFrame.Content).OpenFileActivated(args);
var selectedView = await createMainPageAsync();
if (null != selectedView)
{
selectedView.StartViewInUse();
var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(
selectedView.Id,
ViewSizePreference.Default,
ApplicationView.GetForCurrentView().Id,
ViewSizePreference.Default
);
await selectedView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
var currentPage = (MainPage)((Frame)Window.Current.Content).Content;
Window.Current.Activate();
currentPage.OpenFileActivated(args);
});
selectedView.StopViewInUse();
}
}
else
{
Frame rootFrame = new Frame();
rootFrame.Navigate(typeof(MainPage), args);
Window.Current.Content = rootFrame;
Window.Current.Activate();
alreadyLaunched = true;
}
}
partial void Construct();
partial void OverrideOnLaunched(LaunchActivatedEventArgs args, ref bool handled);
partial void InitializeRootFrame(Frame frame);
partial void OverrideOnLaunched(LaunchActivatedEventArgs args, ref bool handled)
{
// Check if a secondary view is supposed to be shown
ViewLifetimeControl ViewLifetimeControl;
handled = TryFindViewLifetimeControlForViewId(args.CurrentlyShownApplicationViewId, out ViewLifetimeControl);
if (handled)
{
var task = ViewLifetimeControl.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Window.Current.Activate();
});
}
}
partial void InitializeRootFrame(Frame frame)
{
mainDispatcher = Window.Current.Dispatcher;
mainViewId = ApplicationView.GetForCurrentView().Id;
}
bool TryFindViewLifetimeControlForViewId(int viewId, out ViewLifetimeControl foundData)
{
foreach (var ViewLifetimeControl in SecondaryViews)
{
if (ViewLifetimeControl.Id == viewId)
{
foundData = ViewLifetimeControl;
return true;
}
}
foundData = null;
return false;
}
private async Task<ViewLifetimeControl> createMainPageAsync()
{
ViewLifetimeControl viewControl = null;
await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
// This object is used to keep track of the views and important
// details about the contents of those views across threads
// In your app, you would probably want to track information
// like the open document or page inside that window
viewControl = ViewLifetimeControl.CreateForCurrentView();
viewControl.Title = DateTime.Now.ToString();
// Increment the ref count because we just created the view and we have a reference to it
viewControl.StartViewInUse();
var frame = new Frame();
frame.Navigate(typeof(MainPage), viewControl);
Window.Current.Content = frame;
// This is a change from 8.1: In order for the view to be displayed later it needs to be activated.
Window.Current.Activate();
//ApplicationView.GetForCurrentView().Title = viewControl.Title;
});
((App)App.Current).SecondaryViews.Add(viewControl);
return viewControl;
}
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
//I call this function from MainPage.xaml.cs to try to open a new window
public async void LoadNewView()
{
var selectedView = await createMainPageAsync();
if (null != selectedView)
{
selectedView.StartViewInUse();
var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(
selectedView.Id,
ViewSizePreference.Default,
ApplicationView.GetForCurrentView().Id,
ViewSizePreference.Default
);
await selectedView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
var currentPage = (MainPage)((Frame)Window.Current.Content).Content;
Window.Current.Activate();
currentPage.LoadNewFile();
});
selectedView.StopViewInUse();
}
}
}
我用来尝试从 MainPage.xaml.cs 启动新视图/窗口的代码:
((App)App.Current).LoadNewView();
我一直在阅读 Microsoft 文档以尝试了解问题所在,但我仍然不明白多视图究竟是如何工作的,例如每次打开新视图/窗口时都会实例化 App 类。
非常感谢您的帮助。
【问题讨论】:
-
此代码
currentPage.LoadNewFile();正在调用主页的 LoadNewFile。您是否在 Mainpage.xaml.cs 中编写了另一个LoadNewFile()方法?为什么将所有代码都放在 App.xaml.cs 中?最好上传所有代码。 -
是的,我确实在 MainPage.xaml.cs 中编写了 LoadNewFile() 方法,并将多个视图的所有代码放在 App.xaml.cs 中,因此我不必重写代码,但我确实尝试从我的 MainPage.xaml.cs 创建新的视图/窗口,但错误相同。当 CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => 在 createMainPageAsync() 方法中运行时应用程序崩溃,最奇怪的是它试图打开另一个调试器而不是 Visual Studio
-
在这种情况下,请上传所有代码,否则没有错误代码,错误详细信息,人们无法帮助您。
标签: c# uwp windows-10 win-universal-app