Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin Android: Keep control with Alert Dialog until a button is clicked

We are using a static Alert Dialog to get confirmation from the user for certain actions. In our call to Show() we want to keep control until the user clicks a button so that we can return the button click result at the end of the Show() call.

Our iOS version (a UIAlertView) uses

while (displayed)
{
    MonoTouch.Foundation.NSRunLoop.Current.RunUntil(
            MonoTouch.Foundation.NSDate.FromTimeIntervalSinceNow(0.2));
}

in its Show() method to wait for user input prior to returning their button selection as a result.

Is there an Android equivalent to this that we can leverage in Monodroid?

like image 457
my code smells Avatar asked May 17 '13 19:05

my code smells


2 Answers

Solved via a different design:

Instead of waiting for the user to interact with the dialog, and blocking everything else, we instead provide an EventHandler in our call to the static Show method that fires when the user clicks a button:

public static void Show(string title, 
                        string message, 
                        Context context,
                        EventHandler handler,
                        ConfirmationAlertButton button) { ... }

We maintain a private reference to the passed in EventHandler that gets triggered on the button click like so:

private static void OkClicked(object sender, DialogClickEventArgs e)
{
    if (_handler != null)
    {
        _handler.Invoke(sender, e);
    }

    _instance.Dismiss();
    _instance = null;
    _handler = null;
}

Here is an example of what a call to Show looks like from an Activity:

ConfirmationDialog.Show(@"Message title",
                        @"Message text",
                        this,
                        delegate
                        {
                            if (e.Result)
                            {
                                Finish();
                            }
                            else
                            {
                                Invalidate();
                            }
                        },
                        ConfirmationAlertButton.OK);

If anyone would like more information on using a static dialog in their Xamarin Android application, just let me know!

like image 127
my code smells Avatar answered Oct 06 '22 17:10

my code smells


I've solved this problem by creating a AlertDialogHelper class that shows the dialog for me. Just wanted to share my solution with you guys.

Helper class

public class AlertDialogHelper : Java.Lang.Object, IDialogInterfaceOnDismissListener
{
    Context context;
    ManualResetEvent waitHandle;
    string title;
    string message;
    string positiveButtonCaption;
    string negativeButtonCaption;
    bool dialogResult;

    public static async Task<bool> ShowAsync(Context context, string title, string message)
    {
        return await AlertDialogHelper.ShowAsync(context, title, message, "OK", "Cancel");
    }

    public static async Task<bool> ShowAsync(Context context, string title, string message, string positiveButton, string negativeButton)
    {
        return await new AlertDialogHelper(context, title, message, positiveButton, negativeButton).ShowAsync();
    }

    private AlertDialogHelper(Context context, string title, string message, string positiveButton, string negativeButton)
    {
        this.context = context;
        this.title = title;
        this.message = message;
        this.positiveButtonCaption = positiveButton;
        this.negativeButtonCaption = negativeButton;
    }

    private async Task<bool> ShowAsync()
    {
        this.waitHandle = new ManualResetEvent(false);
        new AlertDialog.Builder(this.context)
            .SetTitle(this.title)
            .SetMessage(this.message)
            .SetPositiveButton(this.positiveButtonCaption, OnPositiveClick)
            .SetNegativeButton(this.negativeButtonCaption, OnNegativeClick)
            .SetOnDismissListener(this)
            .Show();

        Task<bool> dialogTask = new Task<bool>(() =>
        {
            this.waitHandle.WaitOne();
            return this.dialogResult;
        });
        dialogTask.Start();
        return await dialogTask;
    }

    private void OnPositiveClick(object sender, DialogClickEventArgs e)
    {
        this.dialogResult = true;
        this.waitHandle.Set();
    }

    private void OnNegativeClick(object sender, DialogClickEventArgs e)
    {
        this.dialogResult = false;
        this.waitHandle.Set();
    }

    public void OnDismiss(IDialogInterface dialog)
    {
        this.dialogResult = false;
        this.waitHandle.Set();
    }
}

Usage

// Default buttons
bool dialogResult = await AlertDialogHelper.ShowAsync(this, "Dialog title", "Some informative message.");

// Custom buttons
bool dialogResult = await AlertDialogHelper.ShowAsync(this, "Dialog title", "Some informative message.", "Yes", "No");
like image 28
Physikbuddha Avatar answered Oct 06 '22 16:10

Physikbuddha