Почему этот метод не ждет? - PullRequest
0 голосов
/ 21 марта 2020

У меня есть всплывающее окно, использующее расширение всплывающих окон rg plugins, которое должно отправлять логическое значение с помощью центра сообщений, но метод, который вызывает это всплывающее окно, никогда не ждет результата.

Ниже вы, ребята, можете увидеть файл DisplayAlert.cs , у него есть метод, который показывает модальное окно и получает логическое значение с помощью центра сообщений:

using Rg.Plugins.Popup.Extensions;
using Xamarin.Forms;
using System.Threading.Tasks;

namespace MasterDetailPageNavigation.XAML
{
    public class Alerta
    {
        public Alerta(){}

        public class Retorno
        {
            public bool valor { get; set; }
        }

        public bool retorno;
        public async Task<bool> ShowAlert(string tipo, string titulo, string msg, string btnconfirm, string btncancel)
        {
            await App.Current.MainPage.Navigation.PushPopupAsync(
                new DisplayAlert(tipo, titulo, msg, btnconfirm, btncancel)
            );

            MessagingCenter.Subscribe<Retorno>(this, "DisplayAlert", (value) =>
            {
                retorno = value.valor;
            });

            return retorno;
        }
    }
}

Это код всплывающего ContentPage, и, как я уже сказал, он должен возвращать true или false путем Центр сообщений:

using Xamarin.Forms;
using Rg.Plugins.Popup.Pages;
using Rg.Plugins.Popup.Extensions;

namespace MasterDetailPageNavigation.XAML
{
    public partial class DisplayAlert : PopupPage
    {
        public DisplayAlert(string tipo, string titulo, string msg,string btnconfirm=null,string btncancel=null)
        {
            InitializeComponent();
            switch (tipo)
            {
                case "ok":
                    XIcon.Text = "\uf058";
                    XIcon.TextColor = Color.FromHex("#009570");
                    break;

                case "error":
                    XIcon.Text = "\uf06a";
                    XIcon.TextColor = Color.FromHex("#FF0000");
                    break;

                case "confirm":
                    XIcon.Text = "\uf059";
                    XIcon.TextColor = Color.FromHex("#2181DF");
                    XBotoes.IsVisible = true;
                    XOk.IsVisible = false;
                    XConfirmar.Text = btnconfirm != null ? btnconfirm : XConfirmar.Text;
                    XCancelar.Text = btncancel != null ? btncancel : XCancelar.Text;
                    break;
            }

            XTitulo.Text = titulo;
            XMsg.Text = msg;
        }

        void XOk_Clicked(System.Object sender, System.EventArgs e)
        {
            Navigation.PopPopupAsync();
        }

        public class Retorno
        {
            public bool valor { get; set; }
        }

        void XConfirmar_Clicked(System.Object sender, System.EventArgs e)
        {
            MessagingCenter.Send(new Retorno() { valor = true }, "DisplayAlert");
        }

        void XCancelar_Clicked(System.Object sender, System.EventArgs e)
        {
            MessagingCenter.Send(new Retorno() { valor = false }, "DisplayAlert");
        }
    }
}

И, наконец, в главном окне я вызываю и жду метод:

Alerta alerta = new Alerta();

// IT SHOULD AWAIT HERE BUT DON'T
bool opt = await alerta.ShowAlert("confirm", "Do you confirm?", "Message asking for confirmation","Exit","Continue here");

if (opt) //it's always false
{
   Application.Current.Properties.Clear();
   await Application.Current.SavePropertiesAsync();
   Application.Current.MainPage = new Login();
}

Где я делаю неправильно или пропустил?

1 Ответ

1 голос
/ 21 марта 2020

Используйте TaskCompletionSource и верните задачу, ожидая вызова делегата.

public class Alerta {
    public Task<bool> ShowAlert(string tipo, string titulo, string msg, string btnconfirm, string btncancel) {
        TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
        var popup = new DisplayAlert(tipo, titulo, msg, btnconfirm, btncancel) {
            TaskSource = tcs
        };
        //show popup
        App.Current.MainPage.Navigation.PushPopupAsync(popup);

        return tcs.Task; //task to be awaited
    }
}

Но для этого потребуется некоторый рефакторинг

public partial class DisplayAlert : PopupPage {
    public DisplayAlert(string tipo, string titulo, string msg,string btnconfirm=null,string btncancel=null) {
        InitializeComponent();
        switch (tipo) {
            case "ok":
                XIcon.Text = "\uf058";
                XIcon.TextColor = Color.FromHex("#009570");
                break;
            case "error":
                XIcon.Text = "\uf06a";
                XIcon.TextColor = Color.FromHex("#FF0000");
                break;
            case "confirm":
                XIcon.Text = "\uf059";
                XIcon.TextColor = Color.FromHex("#2181DF");
                XBotoes.IsVisible = true;
                XOk.IsVisible = false;
                XConfirmar.Text = btnconfirm != null ? btnconfirm : XConfirmar.Text;
                XCancelar.Text = btncancel != null ? btncancel : XCancelar.Text;
                break;
        }

        XTitulo.Text = titulo;
        XMsg.Text = msg;
    }

    public TaskCompletionSource<bool> TaskSource { get; set; }

    void XOk_Clicked(System.Object sender, System.EventArgs e) {
        Navigation.PopPopupAsync();
    }

    void XConfirmar_Clicked(System.Object sender, System.EventArgs e) {
        Navigation.PopPopupAsync();
        TaskSource.SetResult(true);
    }

    void XCancelar_Clicked(System.Object sender, System.EventArgs e) {
        Navigation.PopPopupAsync();
        TaskSource.SetResult(false);
    }
}
...