How to update UI after async Task in viewmodel

bCliksbCliks USMember
edited August 2016 in Xamarin.Forms

I have a xaml page with label. I want to update labelafter some async task. In my ViewModel constructor I set default text for my label. And create a async Task function named SomeTask().

Question 1: Where can I call SomeTask() function. Not able to call async Task function in constructor.
Question 2: How can I update Label text after async Task SomeTask() function.

    public class MyPageViewModel : ViewModelBase
    {  
        private String _selectedText;
        public String SelectedText
        {
            get { return _selectedText; }
            set {
                if (_selectedText != value)
                {
                    _selectedText = value;          
                }       
            }
        }

        public MyPageViewModel ()
        {
            _selectedText = "Welcome";   //Default text
        }

        private async Task<string> SomeTask()
        {            
            return await Task.Run(async () =>
            {
                await Task.Delay(3000); //Dummy task. It will return the status of Task.
                return "Thanks";         //Update Text       
            });         
        }
    }

Best Answers

Answers

  • JacobPoulsen_JacobPoulsen_ DKMember ✭✭✭

    Q1 : I sometimes change it to async void but this will cause a warning to appear since its not best practice to do so. You could also call the Task in the OnAppearing method.

    Q2 :

    private async Task SomeTask()
        {            
                await Task.Delay(3000);     //Dummy task. It will return the status of Task.
                SelectedText = "Thanks";         //Update Text           
        }
    

    Does the above work for you?

  • bCliksbCliks USMember
    edited August 2016

    @JacobPoulsen_

    You could also call the Task in the OnAppearing method.

    Tried on OnAppearingmethod in ViewModel.

    protected virtual async void OnAppearing()
            {
                    await SomeTask();
             }
    
    private async Task SomeTask()
            {            
                    await Task.Delay(3000);     //Dummy task. It will return the status of Task.
                    SelectedText = "Thanks";         //Update Text           
            }
    

    But it doesn't update the SelectedText label value in UI.

    since its not best practice to do so.

    So what is the best practice for handling async tasks in an MVVM.

    Thanks.

  • JohnHardmanJohnHardman GBUniversity mod

    @bCliks - Do you have the Text property of a Label bound to SelectedText ? @JacobPoulsen 's code appears to be making that assumption.

    If not, then either add a binding, or add

    label.Text = SelectedText
    

    where label is the instance of the Label in the UI hierarchy.

  • bCliksbCliks USMember
    edited August 2016

    @JohnHardman

    Do you have the Text property of a Label bound to SelectedText ?

    Yes. I have.

    Without async Task it is working perfectly.

  • bCliksbCliks USMember
    edited August 2016

    @NMackay

    In my viewmodel (works)

    It works. But it didn't wait for task to complete. Just update UI. I want to wait to complete my task.
    Herewith I have attached my portable project for reference. Please check MainPage.xaml, MainPage.xaml.cs and MainPageViewModel.cs

    Thanks.

  • NMackayNMackay GBInsider, University mod
    edited August 2016

    @bCliks

    Try this.

    In your viewmodel.

            public async Task<bool> SomeTask()
            {
    
                await Task.Delay(10000);
                CurrentUser = "Thanks";
                return true;
            }
    

    In your page (view)

            protected override async void OnAppearing()
            {
                await ((HomeViewModel) BindingContext).SomeTask();
            }
    

    I tested and it works fine.

  • bCliksbCliks USMember
    edited August 2016

    @NMackay

    I tested and it works fine.

    Tried on OnAppearingmethod too. But It didn't update UI. Am I missing something?!
    Herewith I have attached my Updated portable project for reference. Please check MainPage.xaml, MainPage.xaml.cs and MainPageViewModel.cs

  • JohnHardmanJohnHardman GBUniversity mod

    @bCliks - a PropertyChanged event, otherwise the property may be set but the binding won't update the UI

  • JohnHardmanJohnHardman GBUniversity mod

    @NMackay - Snap :-)

  • JontyJonty Member ✭✭

    For anyone looking to achieve this from their ViewModel constructor:

    public HomeViewModel()
    {
        Task.Run(async () => await BindViewModel()).Wait();
    }
    
    public async Task BindViewModel()
    {
        eBookRest eBookRest = new eBookRest();
    
        eBooks = new List<eBook>(await eBookRest.RefreshDataAsync());
    }
    

    Your UI will only update/show once the Task has completed because of the Wait() command.

  • AfzalAliAfzalAli USMember ✭✭

    @Jonty said:
    For anyone looking to achieve this from their ViewModel constructor:

    public HomeViewModel()
    {
        Task.Run(async () => await BindViewModel()).Wait();
    }
    
    public async Task BindViewModel()
    {
        eBookRest eBookRest = new eBookRest();
    
        eBooks = new List<eBook>(await eBookRest.RefreshDataAsync());
    }
    

    Your UI will only update/show once the Task has completed because of the Wait() command.

    It worked.

Sign In or Register to comment.