ModalPresentationStyle change via XAML doesn't work

TommigunTommigun Member ✭✭
edited January 19 in Xamarin.iOS

Hi. I am using the latest stable VS for Mac (8.4.1) and the latest stable version (4.4.0.991477) of Xamarin.Forms.

I get the following error:

MyClass.xaml(13,13): Error: XLS0415: The attachable property 'ModalPresentationStyle' was not found in type 'Page'.
with the following XAML:

ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.ModalPresentationStyle="FormSheet"
x:Class="Some.Class"
Title="Some Title"
...

I don't get an error with other iOS platform specifics, such as ios:NavigationPage.HideNavigationBarSeparator="true". If I step into the sources for Page I can see ModalPresentationStyle in there (just like I can see HideNavigationBarSeparator in NavigationPage), so there is no reason for VS to claim it doesn't exist.

What am I doing wrong?

Thanks.

Answers

  • TommigunTommigun Member ✭✭

    FWIW I tried the same from code,
    On().SetModalPresentationStyle(UIModalPresentationStyle.FormSheet);
    which compiles without error, but doesn't do anything - the modal dialog is still presented as fullscreen. My simulated devices were running iOS 13.3

  • LandLuLandLu Member, Xamarin Team Xamurai

    I used the same environment to test this on my side. It worked as expected:

    Please notice, this is a modal style for navigation so we need to present the second page with modal design:

    Navigation.PushModalAsync(page);
    

    If you don't want to use platform related code in Forms we could achieve it using custom renderer like:

    [assembly: ExportRenderer(typeof(SecondPage), typeof(CustomPageRenderer))]
    namespace NavigationSample.iOS
    {
        public class CustomPageRenderer : PageRenderer
        {
            public CustomPageRenderer()
            {
            }
    
            public override void WillMoveToParentViewController(UIViewController parent)
            {
                base.WillMoveToParentViewController(parent);
    
                parent.ModalPresentationStyle = UIModalPresentationStyle.PageSheet;
            }
        }
    }
    

    You could refer to my attachement for the specific code.
    I comment out the custom renderer in my sample, however, the ios:Page.ModalPresentationStyle="FormSheet" still worked.

  • TommigunTommigun Member ✭✭

    Thanks for the reply.

    I know some people say it works, and some say it doesn’t. It definitely does not work for me.
    Does anyone know what could cause ONE platform specific not to be available?

  • TommigunTommigun Member ✭✭

    This is how it looks like for me.

  • LandLuLandLu Member, Xamarin Team Xamurai

    This is only a displaying error we could still run it successfully on iOS.
    And this error won't be shown on Visual Studio for Windows. And it won't affect its functionality.
    Have you tried my sample?
    If it still doesn't work on your side, try to post your repo here.

  • TommigunTommigun Member ✭✭
    edited January 22

    Thanks @LandLu, seems like the error is ignored. Still a bug methinks.
    Also I noticed what is going on. The formsheet presentation works ONLY if the modal page lacks a navigation bar.

    This works as expected:
    await Navigation.PushModalAsync(new MyView());

    This doesn't, it shows up as a fullscreen dialog:
    await Navigation.PushModalAsync(new NavigationPage(new MyView());

    I think this is also a bug. Problem is I do want a navigation bar (with a cancel button) in the formsheet dialog. This is nothing exotic as every formsheet page I've seen in any app does sport a navigation bar with a cancel button. It's quite useless without one tbh.

  • LandLuLandLu Member, Xamarin Team Xamurai

    @Tommigun This is not a bug.
    await Navigation.PushModalAsync(new NavigationPage(new MyView()); this code is aiming to push a navigation page with modal style. The root page of the modal navigation stack is the navigation page so we need to place On<iOS>().SetModalPresentationStyle(UIModalPresentationStyle.FormSheet); in the navigation page. Create a custom navigation page like:

    public class CustomNaviPage : Xamarin.Forms.NavigationPage
    {
        public CustomNaviPage(Xamarin.Forms.Page root) : base(root)
        {
            On<iOS>().SetModalPresentationStyle(UIModalPresentationStyle.FormSheet);
        }
    }
    

    Then consume it when navigating:

    var page = new MyView();
    await Navigation.PushModalAsync(new CustomNaviPage(page));
    

    Problem is I do want a navigation bar (with a cancel button) in the formsheet dialog. This is nothing exotic as every formsheet page I've seen in any app does sport a navigation bar with a cancel button.

    The back button will be displayed from the second page of the navigation stack but the root page won't. We have to create a custom renderer for your MyView and then add the cancel button there like:

    public override void ViewWillAppear(bool animated)
    {
        base.ViewWillAppear(animated);
    
        UIBarButtonItem leftItem = new UIBarButtonItem("Cancel", UIBarButtonItemStyle.Plain, (sender, e) =>
        {
            ((SecondPage)Element).popModal();
        });
        NavigationController.TopViewController.NavigationItem.LeftBarButtonItem = leftItem;
    }
    

    Here is the effect:

    I attached my new project here.

Sign In or Register to comment.