UWP - Platform :: DisconnectedException在页面之间导航时
我有以下设置:MainPage xaml-view和SettingPage xaml-view。在SettingPage xaml-view中,我激活了窗口标题栏中的后退按钮,并添加了一个BackRequestedEventArgs。 (此外,我有一个DX12 XAML页面,但它并没有涉及到导航,所以它永远不会被初始化。)UWP - Platform :: DisconnectedException在页面之间导航时
所以我的问题是:如果我点击一个叫做设置的位于MainPage中的flyoutitem,我将导航到SettingPage。后台按钮出现在标题栏中,如果我点击它,我会回到MainPage。现在我再次执行此操作:单击设置,导航到SettingPage。现在,如果我点击后退按钮或关闭窗口,应用程序崩溃并显示以下异常:
Platform :: DisconnectedException^at 0x046BED80。 HRESULT:0x80010108
我的问题:我该如何解决它?
这里是我的代码是:
的MainPage导航:
void MainPage::MenuFlyoutItemSettings_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
this->Frame->Navigate(Windows::UI::Xaml::Interop::TypeName(SettingsPage::typeid));
}
SettingsPage:
// in Constructor
Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->AppViewBackButtonVisibility = Windows::UI::Core::AppViewBackButtonVisibility::Visible;
Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->
BackRequested += ref new Windows::Foundation::EventHandler<
Windows::UI::Core::BackRequestedEventArgs^>(
this, &SettingsPage::App_BackRequested);
void SettingsPage::App_BackRequested(
Platform::Object^ sender,
Windows::UI::Core::BackRequestedEventArgs^ e)
{
Windows::UI::Xaml::Controls::Frame^ rootFrame = dynamic_cast<Windows::UI::Xaml::Controls::Frame^>(Window::Current->Content);
if (rootFrame == nullptr)
return;
// Navigate back if possible, and if the event has not
// already been handled.
if (rootFrame->CanGoBack && e->Handled == false)
{
e->Handled = true;
rootFrame->GoBack();
}
}
另外两种方法都有onSuspending和我手动添加onResuming处理程序,但他们都为空:
//in constructor
Application::Current->Suspending += ref new SuspendingEventHandler(this, &SettingsPage::OnSuspending);
Application::Current->Resuming += ref new EventHandler<Object^>(this, &SettingsPage::OnResuming);
void SettingsPage::OnSuspending(Object^ sender, SuspendingEventArgs^ e) {
}
void SettingsPage::OnResuming(Object^ sender, Object^ e) {
}
注意:如果我删除整个后台代码,应用程序永远不会因此异常而崩溃,所以我认为这是此代码中的错误。
编辑2017年9月4日:
上Sunteen武工作之后 - 从下面MSFT的答案我意识到,即使我删除所有的后退按钮代码我会尽快为我进入这种例外首次设置页面并关闭应用程序。所以这是我在那里我得到所描述的异常电流的情况:
唯一的代码,我现在已经得到了导航:
的MainPage(在定制settingsbutton):
this->Frame->Navigate(Windows::UI::Xaml::Interop::TypeName(SettingsPage::typeid));
SettingsPage(在自定义后退按钮):
this->Frame->Navigate(Windows::UI::Xaml::Interop::TypeName(MainPage::typeid));
所以我第一次按settingsbutton我得到的描述例外只有当我关机个导航到settingspage后e应用程序(如果点击红色x或停止调试器,也是如此)。导航工作正常,但我可以在页面之间切换,只要我想要,并且在运行应用程序时我不会得到异常。
最终答案2017年9月6日:
结合Sunteen武 - MSFT的回答与上面提到的删除
Application::Current->Suspending += ref new SuspendingEventHandler(this, &SettingsPage::OnSuspending);
Application::Current->Resuming += ref new EventHandler<Object^>(this, &SettingsPage::OnResuming);
处理是我的解决方案。现在没有Disconnectedexception并且后退按钮逻辑也在工作!
Platform :: DisconnectedException^at 0x046BED80。 HRESULT:0x80010108
其实你正在遇到周期问题。关于它的周期问题以及如何解决请参考Weak references and breaking cycles (C++/CX)。当您订阅BackRequested
事件句柄时遇到了周期问题。随着WeakReference
,你会发现这个问题:
WeakReference wr(this);
Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->
BackRequested += ref new Windows::Foundation::EventHandler<
Windows::UI::Core::BackRequestedEventArgs^>([wr](
Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ e)
{
SettingsPage^ c = wr.Resolve<SettingsPage>();
if (c != nullptr)
{
Windows::UI::Xaml::Controls::Frame^ rootFrame = dynamic_cast<Windows::UI::Xaml::Controls::Frame^>(Window::Current->Content);
if (rootFrame == nullptr)
return;
if (rootFrame->CanGoBack && e->Handled == false)
{
e->Handled = true;
rootFrame->GoBack();
}
}
else
{
throw ref new DisconnectedException();
}
});
从文章,当一个事件处理程序抛出DisconnectedException
,它导致事件从用户列表中删除的处理程序。为了解决这个问题,你可以在请求后从用户列表中删除事件句柄。以下代码片段展示了如何删除。
Windows::Foundation::EventRegistrationToken cookie;
SettingsPage::SettingsPage()
{
InitializeComponent();
...
cookie = Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->
BackRequested += ref new Windows::Foundation::EventHandler<
Windows::UI::Core::BackRequestedEventArgs^>(
this, &SettingsPage::App_BackRequested);
}
void SettingsPage::App_BackRequested(
Platform::Object^ sender,
Windows::UI::Core::BackRequestedEventArgs^ e)
{
...
Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->
BackRequested -= cookie;
}
此外,我建议你订阅内App.xaml.cpp
这个事件来避免这个问题。
void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e)
{
auto rootFrame = dynamic_cast<Frame^>(Window::Current->Content);
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == nullptr)
{
...
}
else
{
...
}
Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->
BackRequested += ref new Windows::Foundation::EventHandler<
Windows::UI::Core::BackRequestedEventArgs^>(
this, &App::App_BackRequested);
}
void App::App_BackRequested(
Platform::Object^ sender,
Windows::UI::Core::BackRequestedEventArgs^ e)
{
...
}
更多细节可以参考BackButton官方样片:你可以像如下订阅这里面OnLaunched
。
感谢您的解释,唯一存在的问题是,第一次导航到设置后,如果关闭应用程序后,我仍然得到“Platform :: DisconnectedException ^在0x047FF328。HRESULT:0x80010108” (但不是在第二次回来之后,在后退导航之后再也不会)。我在SettingsPage.xaml.cpp中使用了你的“cookie”片段(通过cookie添加处理程序= ...并且在AppBackRequested中,我使用了我的代码,添加了你的 - = cookie行),我使用了App中的最后一个片段。 xaml.cpp。 – David
@David,你可以试试'App.xaml.cpp'中的代码片段吗?(删除设置页面中的代码)。 –
我已经删除设置页面中的所有相关代码,从App.xaml.cpp写入onLaunched()中的cookie =(...),并编写了我在我的问题中加上的AppBackRequested方法代码以及您的(..) - = App.xaml.cpp中的cookie。现在我可以第一次回去,在第二次导航到settingspage时,我不能交换回MainPage - 单击后退按钮时什么也没有发生。此外,关闭应用程序之后的例外仍然存在,就像我以前的评论一样。 – David