Wednesday 23 January 2019

Modal Pages

Every page has an independent Modal Stack, that means that each page we navigate to has it's own stack of modal pages that can have modals pushed and popped to and from them, however by default a modal blocks all functionality underneath it and thus only one model can be "Active" at one time.

Let's create a modal page


<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="pav.StackNavigation.Views.ModalPage">
    <ContentPage.Content>
        <StackLayout>
            <Label Text="This is a modal page"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="CenterAndExpand" />
            <Button Text="back"
                x:Name="Back_Button"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="CenterAndExpand" />
            <Button Text="Modal"
                x:Name="Modal_Button"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>


our modal page has a back button and a modal button


using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace pav.StackNavigation.Views
{
  [XamlCompilation(XamlCompilationOptions.Compile)]
  public partial class ModalPage : ContentPage {
    public ModalPage () {
      InitializeComponent ();
      Back_Button.Clicked += async (s,e)=> await this.Navigation.PopModalAsync();
      Modal_Button.Clicked += async (se) => await this.Navigation.PushModalAsync(new ModalPage());
    }
  }
}


the back button pops the current modal off our modal stack, whereas the modal button simply pushes another instance of our modal page onto the modal stack, this lets us populate our modal stack with multiple modals and we have to pop each one of them off to get back to our modals containing page.

if you take a look at the modal page you'll notice that that normal header back button is not present


however most devices have a dedicated back button which will pop the modal off the modal stack just the way it should, to block this behavior you can override the OnBackButtonPressed function.


using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace pav.StackNavigation.Views
{
  [XamlCompilation(XamlCompilationOptions.Compile)]
  public partial class ModalPage : ContentPage {
    public ModalPage () {
      InitializeComponent ();
      Back_Button.Clicked += async (s,e)=> await this.Navigation.PopModalAsync();
      Modal_Button.Clicked += async (se) => await this.Navigation.PushModalAsync(new ModalPage());
      Second_Button.Clicked += async (se) => await this.Navigation.PushAsync(new SecondPage());
    }

    protected override bool OnBackButtonPressed() {
      return true// block back button
      return false// pop current modal
    }
  }
}


now if you try to push to the normal stack while on a Modal stack you'll get an exception


which is probably a good thing since navigating to a normal page from a modal would be ridiculous.