await DisplayAlert for Simple Messages

akosititoakositito Member ✭✭

Is it necessary to await the DisplayAlert for simple messages? ex: "Are you sure you want to exit?" , "Cancel transaction?"

TIA

Best Answers

  • Amar_BaitAmar_Bait DZ ✭✭✭✭✭
    edited June 2018 Accepted Answer

    TLDR: If you have a function that returns a Task< Something >, you need to await that function to get the Something.

    DisplayAlert (with 2 buttons) returns a Task< bool >.

    var yesSelected = DisplayAlert("Question", "Are you sure?", "Yes", "No"); // the call is not awaited, 
    // so as soon as the alert is displayed, the next line will be executed, without waiting for the user choice
    
     if (yesSelected )  // compile error: Can't convert Task<bool> to bool
    {
    }
    
    

    In the other hand if you await:

    var yesSelected = await DisplayAlert("Question", "Are you sure?", "Yes", "No"); // the call is awaited
    // the execution is stopped here, the next line won't be executed until the user chooses Yes or No
    
     if (yesSelected )  // No compile error, as the result will be bool, since we awaited the Task<bool>
    {
    }
    
    

    Now, DisplayAlert with one button returns a Task only, since there is only one button, we don't need to know the result (user can only tap on that button). You can think of Task vs Task< Something> as a C# method (no return needed) vs a function that returns Something.

    So in our case of DisplayAlert with one button, to await it or not depends on what you want to do. If the action following the Alert need to be done after the user taps the button, then you need to await DisplayAlert. For eg. you need to logout the user, so you display to him a message explaining that he will be logged out (maybe his access token expired). Here it's better to await for the user until he taps the button to do it, to avoid confusing the user (preparing him for what will happen next). In the other hand, if you want to proceed in parallel (don't want to wait until the user taps), you don't have to await the alert (even though personally, I always awaits a Task as a good practice, as exceptions in non awaited tasks are swallowed).

    Hope it's clear. Also try to forget (nearly) everything you learned in WinForms.

Answers

  • JohnHardmanJohnHardman GBUniversity mod

    @akositito said:
    Is it necessary to await the DisplayAlert for simple messages? ex: "Are you sure you want to exit?"

    As that example is asking a question with two possible answers (yes/no, ok/cancel), you will need to get the boolean result from DisplayAlert, so would have to await it.

    Even in the case where you are not asking a question so there is only one outcome, you would normally want to await the Task returned. Do you absolutely have to - no, but it's good practice and is likely a better fit in apps that use async a lot.

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    I don't use the OEM DisplayAlert so let me ask a question for clarity.
    Does the await in this case wait for the display to be closed... Or does it return once the alert has gone up? A lot of these await calls are for the first action that happens, not the entire workflow the developer is expecting.

  • JohnHardmanJohnHardman GBUniversity mod
    edited June 2018

    @ClintStLaurent said:
    I don't use the OEM DisplayAlert so let me ask a question for clarity.
    Does the await in this case wait for the display to be closed... Or does it return once the alert has gone up? A lot of these await calls are for the first action that happens, not the entire workflow the developer is expecting.

    As best I recall, there are two forms of DisplayAlert, one that returns Task and one that returns Task < bool >. The latter is used when there are two buttons rather than one. As it wouldn't make sense to have two buttons without doing something different depending on the response, that one has to be awaited to get the user's choice. The former, however, presents one button, and is typically used to tell the user something. Whilst I would await that, it's not necessary in all situations.

    Having said that, I am not a big fan of the standard DisplayAlert as it doesn't give as much control as I would like. I currently have a wrapper around it so that I can replace DisplayAlert with something better (testable, cancelable, injectable, configurable) in the not too distant future

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    So @JohnHardman You're saying the await on DisplayAlert returns after the alert has closed, not after it has been displayed. That's what I was confirming.

    Yeah, I use rg.plugins.popups for all of this stuff. Made a UserResponsePopup class that I can feed Title, Body, and Entry for information entered and a collection of button captions. It then displays a notice with 1:n buttons for the response list.

  • NMackayNMackay GBInsider, University mod
    edited June 2018

    The forms layer makes it awaitable, underneath it's not awaitable (certainly in IOS and Android) and uses callbacks.

    I had to write a custom implementation for iOS, Android & UWP before, you end up with lovely code like this....

    private bool AlertConfirm(string title, string content, string confirmButton, string cancelButton, Action<bool> callback)
            {
                UIApplication.SharedApplication.InvokeOnMainThread(() =>
                {
                    var alert = UIAlertController.Create(title, content, UIAlertControllerStyle.Alert);
                    alert.AddAction(UIAlertAction.Create(confirmButton, UIAlertActionStyle.Default, action => callback(true)));
                    alert.AddAction(UIAlertAction.Create(cancelButton, UIAlertActionStyle.Cancel, action => callback(false)));
                    var controller = UIApplication.SharedApplication.KeyWindow.RootViewController;
    
                    while (controller.ModalViewController != null)
                    {
                        controller = controller.ModalViewController;
                    }
    
                    controller.PresentViewController(alert, true, null);
                });
    
                return true;
            }
    
  • akosititoakositito Member ✭✭
    edited June 2018
    > As that example is asking a question with two possible answers (yes/no, ok/cancel), you will need to get the boolean result from DisplayAlert, so would have to await it.
    >
    > Even in the case where you are not asking a question so there is only one outcome, you would normally want to await the Task returned. Do you absolutely have to - no, but it's good practice and is likely a better fit in apps that use async a lot.

    @JohnHardman

    Do you mean i will get unexpected results if a want a boolean result from DisplayAlert without await?

    I think i am missing something here.
  • JohnHardmanJohnHardman GBUniversity mod

    @akositito said:
    Do you mean i will get unexpected results if a want a boolean result from DisplayAlert without await?

    How do you propose getting the boolean result from DisplayAlert if not using await? Remember that you don't want to block the UI thread.

  • JohnHardmanJohnHardman GBUniversity mod

    @NMackay said:
    I had to write a custom implementation for iOS, Android & UWP

    Any reason that you didn't use rg.plugins.popups , or was it just not available when you needed it?

  • akosititoakositito Member ✭✭
    > @JohnHardman said:
    > @akositito said:
    > Do you mean i will get unexpected results if a want a boolean result from DisplayAlert without await?
    >
    >
    >
    >
    >
    > How do you propose getting the boolean result from DisplayAlert if not using await? Remember that you don't want to block the UI thread.

    Sorry, i assumed that it works like MessageBox from winform.

    Can you explain this further? Thanks!
  • JohnHardmanJohnHardman GBUniversity mod

    @akositito

    For more info about popups, see https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/navigation/pop-ups
    For info about async/await and all things Xamarin, sign up for a free account at https://university.xamarin.com/

  • Amar_BaitAmar_Bait DZMember ✭✭✭✭✭
    edited June 2018 Accepted Answer

    TLDR: If you have a function that returns a Task< Something >, you need to await that function to get the Something.

    DisplayAlert (with 2 buttons) returns a Task< bool >.

    var yesSelected = DisplayAlert("Question", "Are you sure?", "Yes", "No"); // the call is not awaited, 
    // so as soon as the alert is displayed, the next line will be executed, without waiting for the user choice
    
     if (yesSelected )  // compile error: Can't convert Task<bool> to bool
    {
    }
    
    

    In the other hand if you await:

    var yesSelected = await DisplayAlert("Question", "Are you sure?", "Yes", "No"); // the call is awaited
    // the execution is stopped here, the next line won't be executed until the user chooses Yes or No
    
     if (yesSelected )  // No compile error, as the result will be bool, since we awaited the Task<bool>
    {
    }
    
    

    Now, DisplayAlert with one button returns a Task only, since there is only one button, we don't need to know the result (user can only tap on that button). You can think of Task vs Task< Something> as a C# method (no return needed) vs a function that returns Something.

    So in our case of DisplayAlert with one button, to await it or not depends on what you want to do. If the action following the Alert need to be done after the user taps the button, then you need to await DisplayAlert. For eg. you need to logout the user, so you display to him a message explaining that he will be logged out (maybe his access token expired). Here it's better to await for the user until he taps the button to do it, to avoid confusing the user (preparing him for what will happen next). In the other hand, if you want to proceed in parallel (don't want to wait until the user taps), you don't have to await the alert (even though personally, I always awaits a Task as a good practice, as exceptions in non awaited tasks are swallowed).

    Hope it's clear. Also try to forget (nearly) everything you learned in WinForms.

  • akosititoakositito Member ✭✭
    @nadjib

    Why xamarin didn't implement a MessageBox like feature to simplify things?
  • MukeshMukesh Member ✭✭

    @NMackay said:
    The forms layer makes it awaitable, underneath it's not awaitable (certainly in IOS and Android) and uses callbacks.

    I had to write a custom implementation for iOS, Android & UWP before, you end up with lovely code like this....

    private bool AlertConfirm(string title, string content, string confirmButton, string cancelButton, Action<bool> callback)
            {
                UIApplication.SharedApplication.InvokeOnMainThread(() =>
                {
                    var alert = UIAlertController.Create(title, content, UIAlertControllerStyle.Alert);
                    alert.AddAction(UIAlertAction.Create(confirmButton, UIAlertActionStyle.Default, action => callback(true)));
                    alert.AddAction(UIAlertAction.Create(cancelButton, UIAlertActionStyle.Cancel, action => callback(false)));
                    var controller = UIApplication.SharedApplication.KeyWindow.RootViewController;
    
                    while (controller.ModalViewController != null)
                    {
                        controller = controller.ModalViewController;
                    }
    
                    controller.PresentViewController(alert, true, null);
                });
    
                return true;
            }
    

    I ask sir contactView page is not supported the DisplayAlert .
    var result = await DisplayAlert("Question", "Are you sure?", "Yes", "No");
    if (result)
    {
    // user said Yes!!!
    }

    This methods how can resolve this issue and please tell me how can be used your custom alert function used in which section of the IOS pages like appDelegate ya class file ya other than.

Sign In or Register to comment.