UWP - 在页面之间导航时的Platform :: DisconnectedException

时间:2017-08-30 07:42:25

标签: c++ xaml uwp navigation back-button

我有以下设置: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也正常工作!

1 个答案:

答案 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官方样本的详细信息。