locked
modal return RRS feed

  • Question

  • User152486 posted

    Hi, I need to receive a value from modal Page. I win open modal Page but dont win retur one value wuen I pop this. How to do this? Thanks

    Tuesday, April 19, 2016 10:30 PM

Answers

  • User57869 posted

    Use a TaskCompletionSource<T>.

    Here is some sample code from my app:

    public static Task<string> ReadStringInPopup()
    {
        var vm = new ReadStringInPopupViewModel();
        var tcs = new TaskCompletionSource<string>();
    
        Device.BeginInvokeOnMainThread(async () =>
        {
            var page = new PopupPage(new ReadStringInPopupView(), 380, 230, vm);
    
            await Navigation.PushModalAsync(page);
    
            var value = await vm.GetValue();
    
            await Navigation.PopModalAsync();
    
            tcs.SetResult(value);
        });
    
        return tcs.Task;
    }
    

    You can call it simply with:

    string input = await ReadStringInPopup();
    

    My ReadStringInPopupViewModel looks like this:

    private TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
    
    public ReadStringInPopupViewModel()
    {
        OKCommand = new Command(() => tcs.SetResult(InputString));
        CancelCommand = new Command(() => tcs.SetResult(null));
    }
    
    public Task<string> GetValue()
    {
        return tcs.Task;
    }
    

    The commands will be bound to the buttons in the view.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Wednesday, April 20, 2016 7:56 AM

All replies

  • User179286 posted

    You should use the MessengerService IMHO. Also MVVM Frameworks like FreshMVVM offer such functionality.

    Wednesday, April 20, 2016 7:02 AM
  • User57869 posted

    Use a TaskCompletionSource<T>.

    Here is some sample code from my app:

    public static Task<string> ReadStringInPopup()
    {
        var vm = new ReadStringInPopupViewModel();
        var tcs = new TaskCompletionSource<string>();
    
        Device.BeginInvokeOnMainThread(async () =>
        {
            var page = new PopupPage(new ReadStringInPopupView(), 380, 230, vm);
    
            await Navigation.PushModalAsync(page);
    
            var value = await vm.GetValue();
    
            await Navigation.PopModalAsync();
    
            tcs.SetResult(value);
        });
    
        return tcs.Task;
    }
    

    You can call it simply with:

    string input = await ReadStringInPopup();
    

    My ReadStringInPopupViewModel looks like this:

    private TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
    
    public ReadStringInPopupViewModel()
    {
        OKCommand = new Command(() => tcs.SetResult(InputString));
        CancelCommand = new Command(() => tcs.SetResult(null));
    }
    
    public Task<string> GetValue()
    {
        return tcs.Task;
    }
    

    The commands will be bound to the buttons in the view.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Wednesday, April 20, 2016 7:56 AM
  • User179286 posted

    @MichaelRumpler You are creating new Tasks for new Pages?

    Wednesday, April 20, 2016 8:00 AM
  • User57869 posted

    If I want to get the value with

    string input = await ReadStringInPopup();
    

    then Yes, I have to.

    You can omit the Device.BeginInvokeOnMainThread if you always call it from the UI thread, but my code can also be called from a background thread. I need that for some popups, so I added it to all just to be sure.

    E.g. my app needs to load and parse some files. The files can be password protected and in that case, the loading method (which runs on a background thread) raises an event which has to ask for a password. This opens a popup on the UI thread and returns the result. Then the event handler can check the password, set a property in its EventArgs and return to resume parsing the file. This would not be possible with the MessengerService and without a TaskCompletionSource.

    Wednesday, April 20, 2016 8:24 AM
  • User387004 posted

    Awesome! Thanks for the code too! I was using MessagingCenter in the past, but was getting some problems with null exceptions, and so on. I had been using the message enter to pass progress updates for loading large databases. And to manage remote updates to pages. I'll take a look at your code, it sounds like I could actually use it somewhere else as well lol!

    Cheers!

    Friday, February 21, 2020 2:53 AM