web-dev-qa-db-ja.com

PushModalAsyncフォームがxamarinフォームで閉じられるのを待ちます

ページがあり、ツールバーのプラスボタンをクリックすると、ポップアップページが呼び出されます。

ポップアップページから、ユーザーは何もせずに新しいエントリを追加したり、ウィンドウをキャンセル/閉じることができます

すべてが正常に機能しており、コードは次のようになっています

    public partial class SelectSchool : ContentPage
    {
        public SelectSchool()
        {
            InitializeComponent();
            #region toolbar
            ToolbarItem tbi = null;
            if (Device.OS == TargetPlatform.Android)
            {
                tbi = new ToolbarItem("+", "plus", async () =>
                {
                    var target_page = new AddSchool(); 
                    Navigation.PushModalAsync(target_page);                                 
                }, 0,0);
            }
            ToolbarItems.Add(tbi);
            #endregion

            this.Title = "Select School";

        }
    }

そして私のポップアップページは

     public partial class AddSchool : ContentPage
    {
        public AddSchool()
        {
            InitializeComponent();
        }
        private async void Button_OK_Clicked(object sender, EventArgs e)
        {
        //doing some operations like entry to db etc and close page
             Navigation.PopModalAsync();

        }
        private void cancelClicked(object sender, EventArgs e)
        {
            Navigation.PopModalAsync();
        }
    }

しかし今、私はポップアップが閉じて追加のコーディングを行うのを待ちたいので、以下のコードを試しました

 if (Device.OS == TargetPlatform.Android)
            {
                tbi = new ToolbarItem("+", "plus", async () =>
                {
                    var target_page = new AddSchool(); 
                    await Navigation.PushModalAsync(target_page);  
                    //await till target_page is closed and once its closed call my next function here               
                }, 0,0);
            }

しかし、awaitは機能していません。ポップアップが閉じるまで、この領域でどのように待つことができますか?何か案が??

7
Jibin Mathew

モーダルページでDisappearingイベントを使用します。

例:

var modalPage = new ContentPage();
modalPage.Disappearing += (sender2, e2) =>
{
    System.Diagnostics.Debug.WriteLine("The modal page is dismissed, do something now");
};
await content.Navigation.PushModalAsync(modalPage);
System.Diagnostics.Debug.WriteLine("The modal page is now on screen, hit back button");

または、EventWaitHandleを使用します:

var waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
var modalPage = new ContentPage();
modalPage.Disappearing += (sender2, e2) =>
{
    waitHandle.Set();
};
await content.Navigation.PushModalAsync(modalPage);
System.Diagnostics.Debug.WriteLine("The modal page is now on screen, hit back button");
await Task.Run(() => waitHandle.WaitOne());
System.Diagnostics.Debug.WriteLine("The modal page is dismissed, do something now");
14
SushiHangover

ここでの答えは少し遅れていますが、アプリケーションのOnModalPagePoppingイベントハンドラーをリッスンするのが最善かもしれません。

まず、モーダルページを作成します。後で取得するデータを格納するプロパティを指定します。

public class MyModalPage : ContentPage
{
    public string Data { get; set; }

    public MyModalPage()
    {
        InitializeComponent();
        // ... set up the page ...
    }

    private async void PopThisPage()
    {
        // When you want to pop the page, just call this method
        // Perhaps you have a text view with x:Name="PhoneNumber", for example
        Data = PhoneNumber.Text; // store the "return value" before popping
        await MyProject.App.Current.MainPage.Navigation.PopModalAsync();
    }
}

親ページでは、モーダルページを作成し、モーダルページがポップしたときにリッスンするようにイベントハンドラーを設定できます。

public class MyPage : ContentPage
{
    MyModalPage _myModalPage;

    public MyPage()
    {
        InitializeComponent();
        // ... set up the page ...
    }

    private async void ShowModalPage()
    {
        // When you want to show the modal page, just call this method
        // add the event handler for to listen for the modal popping event:
        MyProject.App.Current.ModalPopping += HandleModalPopping;
        _myModalPage = new MyModalPage();
        await MyProject.App.Current.MainPage.Navigation.PushModalAsync(_myModalPage());
    }

    private void HandleModalPopping(object sender, ModalPoppingEventArgs e)
    {
        if (e.Modal == _myModalPage)
        {
            // now we can retrieve that phone number:
            var phoneNumber = _myModalPage.Data;
            _myModalPage = null;

            // remember to remove the event handler:
            MyProject.App.Current.ModalPopping -= HandleModalPopping;
        }
    }

}

これは、OnDisappearingメソッドを使用するよりも優れています。これは、アプリがバックグラウンドで実行されている場合などに呼び出すことができると他の人がすでに述べているためです。また、その動作はプラットフォーム間で一貫していません。

モーダルがナビゲーションスタックから完全にポップされた後に呼び出される別のイベントOnModalPoppedもあります。それを使用する場合は、同様に機能するはずです。

9
sme

イベントを作成して、ポップクローズ時に呼び出すことができます。

public partial class AddSchool : ContentPage
{
    public delegate void PopupClosedDelegate();

    public event PopupClosedDelegate PopupClosed;

    public AddSchool()
    {
        InitializeComponent();
    }
    private async void Button_OK_Clicked(object sender, EventArgs e)
    {
        //doing some operations like entry to db etc and close page
        await Navigation.PopModalAsync();
        if (PopupClosed!=null)
        {
            PopupClosed();
        }
    }
    private async void cancelClicked(object sender, EventArgs e)
    {
        await Navigation.PopModalAsync();
        if (PopupClosed != null)
        {
            PopupClosed();
        }
    }
}

私はそれをボタンクリックイベントに置きました、多分あなたは閉じるか処分イベントを置くことができます。次に、ここに実装があります

public partial class SelectSchool : ContentPage
{
    public SelectSchool()
    {
        InitializeComponent();
        #region toolbar
        ToolbarItem tbi = null;
        if (Device.OS == TargetPlatform.Android)
        {
            tbi = new ToolbarItem("+", "plus", async () =>
            {
                var target_page = new AddSchool();
                target_page.PopupClosed += () => { /*Do something here*/ };
                Navigation.PushModalAsync(target_page);
            }, 0, 0);
        }
        ToolbarItems.Add(tbi);
        #endregion

        this.Title = "Select School";

    }
}

この助けを願っています。

3
zquanghoangz

これを実現するもう1つの方法は、ページのOnDisapearingメソッドからイベントを呼び出すことです。このイベントは、作成したナビゲーションサービスによってサブスクライブされ、ページの作業が完了するまで"TaskCompletionSource"を使用して待機できます。次に、タスクを完了します。これを達成するための詳細については、 このブログ投稿を確認できます。

これがベースページの実装です。このデモアプリのすべてのページはこのページを継承します。

public class BasePage<T> : ContentPage
{
    public event Action<T> PageDisapearing;
    protected T _navigationResut;

    public BasePage()
    {
    }

    protected override void OnDisappearing()
    {
        PageDisapearing?.Invoke(_navigationResut);
        if (PageDisapearing != null)
        {
            foreach (var @delegate in PageDisapearing.GetInvocationList())
            {
                PageDisapearing -= @delegate as Action<T>;
            }
        }
        base.OnDisappearing();
    }
}

使用する必要のあるナビゲーションサービスの概要は次のとおりです。

public async Task<T> NavigateToModal<T>(string modalName)
    {
        var source = new TaskCompletionSource<T>();
        if (modalName == nameof(NewItemPage))
        {
            var page = new NewItemPage();
            page.PageDisapearing += (result) =>
            {
                var res = (T)Convert.ChangeType(result, typeof(T));
                source.SetResult(res);
            };
            await App.Current.MainPage.Navigation.PushModalAsync(new NavigationPage(page));
        }
        return await source.Task;
    }

ナビゲーションサービスでこのページを呼び出すには、次のコードを使用できます。

 var item = await new SimpleNavigationService().NavigateToModal<Item>(nameof(NewItemPage));
        Items.Add(item);
0
Damien Doumer