我有以下设置:MainPage xaml-view和SettingPage xaml-view。在SettingPage xaml-view中,我激活了窗口标题栏中的后退按钮,并添加了BackRequestedEventArgs。 (此外我有一个DX12 xaml页面,但它还没有涉及导航,因此它永远不会被初始化。)
所以我的问题是:如果我点击位于MainPage中的名为settings的flyoutitem,我将导航到SettingPage。后退按钮出现在标题栏中,如果我单击它,我将返回到MainPage。现在我再次这样做:点击设置,导航到SettingPage。现在,如果我点击后退按钮或关闭窗口,应用程序崩溃并向我显示以下异常:
Platform :: DisconnectedException ^位于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));
}
设置页面:
// 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-09-04:
在使用Sunteen Wu之后 - MSFT的答案从下面我意识到,即使我删除了所有的后退代码,我第一次进入SettingsPage时会立即得到此异常并关闭应用程序。所以这是我目前的情况,我得到了描述的异常:
我现在唯一的导航代码:
MainPage(在自定义设置按钮中):
this->Frame->Navigate(Windows::UI::Xaml::Interop::TypeName(SettingsPage::typeid));
SettingsPage(在自定义后退按钮中):
this->Frame->Navigate(Windows::UI::Xaml::Interop::TypeName(MainPage::typeid));
所以在我第一次通过按下设置按钮导航到设置页面后,只有在我关闭应用程序时才会获得描述的异常(如果单击红色x或停止调试器,则相同)。导航工作正常,我可以在页面之间切换,只要我想要,我不会在运行应用程序时得到异常。
最终答复2017-09-06:
结合Sunteen Wu - MSFT的答案删除上述
Application::Current->Suspending += ref new SuspendingEventHandler(this, &SettingsPage::OnSuspending);
Application::Current->Resuming += ref new EventHandler<Object^>(this, &SettingsPage::OnResuming);
处理程序对我来说是解决方案。现在没有Disconnectedexception,Back-Button-Logic也正常工作!
答案 0 :(得分:0)
Platform :: DisconnectedException ^位于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
内订阅此活动以避免此问题。您可以在OnLaunched
内订阅,如下所示:
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官方样本的详细信息。