DisplayActionSheet Popup not opening in xamarin IOS Project

I have implemented xamarin project using MVVM. I wrote button click command in view model. I am trying to open a Displayactionsheet using below code on the button click but Actionsheet is not opening in IOS but in Android it is working fine. If I put the same code in View.cs file then it is working fine in IOS as well. But if I put same code in viewmodel why Action sheet is not opening?

                String[] LogInOptions = {"Option1", "Option2"};
                var action = await App.Current.MainPage..DisplayActionSheet("Log In","Cancel","",LogInOptions);
                switch(action) {
                case "Option1" : {   
                        break;    }
                case "Option2" : {
                        break;  }
                                       }

Answers

  • adamkempadamkemp USInsider, Developer Group Leader mod

    Are you presenting another page modally on top of MainPage? You need to show the action sheet from a page that is currently visible and not presenting another page modally.

  • Let me explain with example.In page1 i have a label.I have attached tap gestures for this label.On tap of label i wrote a command in viewmodel1.In the command i wrote logic to open displayactionsheet as mentioned above .But its working in android not in ios.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    Can you make a small sample project that reproduces the issue and attach it here so I can test it?

  • XXXXXXXXXX USMember

    I am attaching sample project to this mail. Loginpage has displayactionsheet. If i load directly Loginpage from app.cs then Displayactionsheet is showing.But in my app i am navigating to login page from tabbed page. I am guessing issue may be due to navigation but i am unable to find it.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    Based on your example project it looks like you're doing exactly what I warned you about. You are pushing a modal page (the login page) on top of your main page. Then you are trying to use DisplayActionSheet from your main page, which is no longer even visible. You can't display an alert or action sheet from a page that's not visible. You have to do it on the page that is currently on screen.

  • If i load directly Login page from app.cs then Displayactionsheet is showing(Iam opening DisplayActionsheet in view model in the command event) .But in my app i am navigating to login page from tabbed page then only i am facing issue. The issue is not with MVVM I guess.

  • Moreover i am able to open displayalerts in view model using dependency service but not able to open Displayactionsheet.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    If i load directly Login page from app.cs then Displayactionsheet is showing

    I don't know exactly what you mean by this. How are you "directly" loading the login page? Show me the code.

    But in my app i am navigating to login page from tabbed page then only i am facing issue.

    The issue isn't the tabbed page. The issue is the way that you're pushing the login page on top of the main page as a modal. Modal pages don't work like navigation pages. If you push PageB as a modal on top of PageA then PageA is no longer visible in the app, and you can't present another page modally on top of it, nor can you display an alert or an action sheet from PageA. You have to use PageB instead. So PageA.DisplayActionSheet won't work, but PageB.DisplayActionSheet would work. That's essentially the mistake you're making. PageA is your main page (a tabbed page, in this case). PageB is your login page. Once you push that login page as a modal you can't use DisplayActionSheet on MainPage. You have to call it on the login page instance instead.

  • XXXXXXXXXX USMember

    Can you please update the attached project accordingly and attach to this mail.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    What are you not understanding?

  • XXXXXXXXXX USMember

    I got the solution you were saying .But If i push my login page using pushasync iam getting error
    like pushasync is not supported globally in ios. so i am pushing login page modally instead of using pushasync. Iam getting this error because i am pushing profilenavigation page modally before.So all the navigations which happens after we push view modally has to happen only with Pushmodalasync not with pushasync. So can you guide me how can i refine the navigation code so that i can push my loginpage using pushasync to support Displayactionsheet functionality.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    You should read this. It explains the difference between PushAsync and PushModalAsync. The key is that you can only use PushAsync when you have a NavigationPage. That's why you're getting an error. However, the fix for that error isn't necessarily to switch to PushModalAsync. The right fix may be to start using a NavigationPage.

    That's all aside from the issue here, though. The issue here is that you're not understanding the fact that you can't call DisplayActionSheet on a page that isn't visible, and App.Current.MainPage is not guaranteed to be visible. Therefore you shouldn't try to call App.Current.MainPage.DisplayActionSheet(...). That call is not guaranteed to actually work. You should only call DisplayActionSheet on a page that you know for sure is visible.

    Looking at your example, you are calling this method in LoginViewModel. You're presumably using App.Current.MainPage because you have to call this method on a Page, and in your view model you don't have a Page instance. But what you really need to do is to call DisplayActionSheet on the LoginPage instance somehow.

    There are many techniques you can use to do that. One popular approach is MessagingCenter, but I don't personally think that's appropriate here. Another simple possibility is to add an interface that lets you inject the handler into the view model. Let me show you how that works. First, you define the interface:

    public interface IDisplayActionSheet
    {
        Task<string> DisplayActionSheet(string title, string cancel, string destruction, string[] buttons);
    }
    

    Next, you add a public property to your view model using that type:

    public IDisplayActionSheet ActionSheetDisplayer { get; set; }
    

    And instead of using App.Current.MainPage.DisplayActionSheet you use this.ActionSheetDisplayer.DisplayActionSheet. Lastly, you need to implement that interface in your page and inject itself into the view model as the handler:

    public partial class LoginPage : ContentPage, IDisplayActionSheet
    {
        public LoginPage()
        {
            InitializeComponent();
    
            var viewModel = new ViewModel.Login.LoginViewModel();
            viewModel.ActionSheetDisplayer = this;
            this.BindingContext = viewModel;
        }
    }
    

    Since I used the identical signature as the actual DisplayActionSheet method in the Page class I didn't even have to write the method. It's already written.

    If you make those changes then you'll find that this code works, and the action sheet appears. The reason it works is that now instead of calling DisplayActionSheet on a page that's hidden behind a modal (your main page), you're calling it on LoginPage, which is visible.

  • ScottNimrodScottNimrod USMember ✭✭

    I'm having issues getting this to work on Xamarin.Forms Embedded.
    Is this DisplayActionSheet supported using Xamarin.Forms Embedded?

Sign In or Register to comment.