UWP - Platform::DisconnectedException while navigating between pages

0

I've got the following setup: A MainPage xaml-view and a SettingPage xaml-view. In the SettingPage xaml-view I activated the back button which is in the window title bar and I added a BackRequestedEventArgs. (Furthermore I have a DX12 xaml page but it is not involved to the navigation yet, so it will never get initialized.)

So my problem is: if I click on a flyoutitem called settings which is located in the MainPage, I'll get navigated to the SettingPage. The backbutton appears in the titlebar and if I click it, I get back to the MainPage. Now I do it once again: clicking on settings, navigating to SettingPage. Now if I click on the backbutton OR close the window the app crashes and shows me the following exception:

Platform::DisconnectedException ^ at 0x046BED80. HRESULT:0x80010108

My Question: How do I fix it?

Here is my Code for it:

MainPage Navigation:

    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();
    }
}

Furthermore both methods have onSuspending and onResuming handlers added by me manually, but they are both empty:

//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) {


}

NOTE: If I delete the whole backbutton-code, the app never crashes with this exception, so I think it is an error in this code.

EDIT 2017-09-04:

After working on Sunteen Wu - MSFT's Answer from below I realised that even If I delete all the backbutton-code I will get this exception as soon as I enter the SettingsPage the first time and close the app. So here is my current scenario where I am getting the described exception:

The only code I've got now for navigation:

MainPage (in a custom settingsbutton):

this->Frame->Navigate(Windows::UI::Xaml::Interop::TypeName(SettingsPage::typeid));

SettingsPage (in a custom backbutton):

this->Frame->Navigate(Windows::UI::Xaml::Interop::TypeName(MainPage::typeid));

So after the first time I navigate to the settingspage by pressing the settingsbutton I get the described exception only if I shutdown the app (same if clicking on red x or stopping debugger). The navigation works fine though, I can swap between the pages as long as I want and I won't get the exception while running the app.

FINAL ANSWER 2017-09-06:

Combining Sunteen Wu - MSFT's Answer with deleting the above mentioned

Application::Current->Suspending += ref new SuspendingEventHandler(this, &SettingsPage::OnSuspending);
Application::Current->Resuming += ref new EventHandler<Object^>(this, &SettingsPage::OnResuming);

handlers is the solution for me. Now there is no Disconnectedexception and the Back-Button-Logic is also working!

c++
xaml
uwp
navigation
back-button
asked on Stack Overflow Aug 30, 2017 by David • edited Sep 6, 2017 by David

1 Answer

0

Platform::DisconnectedException ^ at 0x046BED80. HRESULT:0x80010108

Actually you are meeting the cycles issue. For what it the cycles issue and how to resolve please reference Weak references and breaking cycles (C++/CX). You met the cycles issue when you subscribe the BackRequested event handle. With the WeakReference you will find the issue:

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(); 
    }
});

From the article, when an event handler throws DisconnectedException, it causes the event to remove the handler from the subscriber list. So that to resolve it, you can remove the event handle from subscriber list after back requested. The following code snippet showed how to remove.

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;
}

Additionally, I recommend you subscribe this event inside App.xaml.cpp to avoid this issue. You can subscribe it inside OnLaunched like follows:

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)
{
     ...
}

More details you can reference BackButton official sample.

answered on Stack Overflow Sep 1, 2017 by Sunteen Wu

User contributions licensed under CC BY-SA 3.0