Immediately update UI when OnClick_Event occurs

Viewed 344

Very simple example:

<StackLayout>
  <Button Text="{Binding LoginButtonText}" Clicked="Button_Clicked"></Button>
</StackLayout>

Code behind:

public partial class ItemsPage : ContentPage
{
  private ViewModels.ItemsViewModel _viewModel;
  public ItemsPage()
  {
    _viewModel = new ItemsViewModel();
    BindingContext = _viewModel;
    InitializeComponent();
  }
  private void Button_Clicked(object sender, EventArgs e)
  {         
    this._viewModel.LoginButtonText = "Start" + DateTime.Now.ToString();
    // this loop is just for testing purposes. To demonstrate 
    // that this loop block UI thread
    for (int i = 0; i < 100; i++)
    {
      for (int j = 0; j < 1000; j++)
      {
        string s = new Random(45).NextDouble().ToString();
      }
    }
    this._viewModel.LoginButtonText = "End " + DateTime.Now.ToString();
  }
} 

I'm using MVVM - INotifyPropertyChanged

public class ItemsViewModel : ObservableObject
{ 
  private string _loginButtonText;
  public string LoginButtonText
  {
    get { return _loginButtonText; }
    set { SetProperty(ref _loginButtonText, value); }
  }
}

ObservableObject implementation can be seen here: https://codeshare.io/G87N74

When I click on the button after a few seconds (4 or 5) the button text gets value 'End 03/08/2017 08:55:33' (will it depends on the current timestamp of course). The button text Start + DateTime does not appear.

It works if I write this:

private void Button_Clicked(object sender, EventArgs e)
{
  this._viewModel.LoginButtonText= "Start" + DateTime.Now.ToString();
  // I assume here execution switches threads as it sees Task as a new thread. While waiting for task to finish
  // it finished mvvm INotifyPropertyChanged change.Invoke call and updates the button text
  await Task.Delay(5000);
  this._viewModel.LoginButtonText = "End " + DateTime.Now.ToString();
}

But it's not 100% as we don't know how threads will be scheduled for execution. Is there a simple way to update UI immediately when we hit event method?

There is a method Device.BeginInvokeOnMainThread() but it returns void, therefore it doesn't block UI.

1 Answers
Related