How to suspend UI / App Shell when manually removin and adding element to App Shell in Xamarin.Forms

My Question:

In Xamarin.Forms 4.2+, can I suspend the App Shell in any way while I am manipulating it? Or can I suspend the whole UI layouting and rending for an instance?

My Situation:

I am creating an App with Xamarin.Forms where I use the new Shell Navigation. Cause I change the Flyout Menu during app runtime, I want to add and remove some of the FlyoutItem by code.

As an example, I have a LoginPage which I want to replace by a UserProfilePage in the App Menu (Flyout Menu). I always have an AppInfoPage in the menu.

Whenever I remove a FlyoutItem, Shell wants to display the next item. So when I remove the LoginPage, Shell displays AppInfoPage or at least calls the constructor and executes the overload of OnAppearing on the AppInfoPage. OnAppearing then does a lot of things to prepare the App info, which is not needed now cause the page will be OnDisappearing just a few ticks later.

Most UI frameworks have some function like this to avoid unneeded UI layouting and rendering. I tried setting IsVisible = false, IsBusy = true and calling BatchBegin(), but none of them helped me.

Answers

  • ColeXColeX Member, Xamarin Team Xamurai
    edited October 10

    You could define two different shell in App , and switch App.MainPage at the right time , then the heavy works would be only executed once .

        AppShell shell = new AppShell();
        AppShell2 shell2 = new AppShell2();
    
        public void setMainPgae1()
        {
            MainPage = shell;
        }
    
        public void setMainPgae2()
        {
            MainPage = shell2;
        }
    
  • thisismyselfthisismyself Member ✭✭

    Thank you for sharing your idea. I very appreciate that. I think it is a good idea and I tried it in a small example. Switching the Shell works. But I am facing two issues:

    1. when switching from second to the first shell, the last shown page of the first shell is shown. But neither constructor nor OnAppearing of this page are called. Means it re-uses the previous instance which might be a problem. Specially cause OnAppearing is not called, thus I am not able to refresh the ViewModel. But this issue is solvable somehow.
    2. The worse problem: When I am back in the first Shell and display the Flyout Menu, the menu is shown but a Crash happens. It is NullReferenceException thrown in Xamarin Code: Xamarin.Forms.Platform.Android.ShellFlyoutRenderer.OnShellPropertyChanged (System.Object sender, System.ComponentModel.PropertyChangedEventArgs e) [0x00017] in D:\a\1\s\Xamarin.Forms.Platform.Android\Renderers\ShellFlyoutRenderer.cs:134

    I am using the latest stable Xamarin.Forms build from nuget: 4.2.0.848062

    I dit no try in iOS.

    A short summary of my code:

    AppShellLogin.xaml:


    <FlyoutItem Title="Login"> <ShellContent ContentTemplate="{DataTemplate local:LoginPage}" Title="Login" Route="go-to-login"/> </FlyoutItem> <FlyoutItem Title="About"> <ShellContent ContentTemplate="{DataTemplate local:AboutPage}" Title="About" Route="go-to-about" /> </FlyoutItem> <FlyoutItem Title="Testsettings"> <ShellContent ContentTemplate="{DataTemplate local:TestSettingsPage}" Title="Testsettings" Route="go-to-testsettings" /> </FlyoutItem>

    AppShell.xaml:


    <FlyoutItem Title="Document"> <ShellContent ContentTemplate="{DataTemplate local:ItemsPage}" Title="Documents" Route="go-to-items" /> </FlyoutItem> <FlyoutItem Title="Logout"> <ShellContent ContentTemplate="{DataTemplate local:LogoutPage}" Title="Logout" Route="go-to-logout"/> </FlyoutItem> <FlyoutItem Title="About"> <ShellContent ContentTemplate="{DataTemplate local:AboutPage}" Title="About" Route="go-to-about"/> </FlyoutItem> <FlyoutItem Title="Testsettings" IsEnabled="False"> <ShellContent ContentTemplate="{DataTemplate local:TestSettingsPage}" Title="Testsettings" Route="go-to-testsettings" /> </FlyoutItem>

    In App.xaml.cs I change the current Shell according to the users state in the App. This is triggered by an Observable over System.Reactive. :


    public App() { InitializeComponent(); MainPage = _loginShell; } private void ChangeShellIfNeeded() { if (AppContext.GetInstance().IsLoggedIn) { MainPage = _mainShell; } else { MainPage = _loginShell; } }
  • thisismyselfthisismyself Member ✭✭

    The crash I described in my previous post is possibly related with an issue already reported by another user to the Xamarin bugtracker:
    https://github.com/xamarin/Xamarin.Forms/issues/7864

    The crash from my previous post:

    1. The worse problem: When I am back in the first Shell and display the Flyout Menu, the menu is shown but a Crash happens. It is NullReferenceException thrown in Xamarin Code: Xamarin.Forms.Platform.Android.ShellFlyoutRenderer.OnShellPropertyChanged (System.Object sender, System.ComponentModel.PropertyChangedEventArgs e) [0x00017] in D:\a\1\s\Xamarin.Forms.Platform.Android\Renderers\ShellFlyoutRenderer.cs:134
Sign In or Register to comment.