JL Tinoco
JL Tinoco

Reputation: 25

Property change in Base ViewModel with prism

I'm using prism to develop an android app.

I'm trying to make a Base ViewModel. Inside this ViewModel I would like to set common properties to all my ViewModels.

  public class BaseViewModel : BindableBase
{
    protected INavigationService _navigationService;
    protected IPageDialogService _dialogService;

    public BaseViewModel(INavigationService navigationService, IPageDialogService dialogService)
    {
        _navigationService = navigationService;
        _dialogService = dialogService;
    }

    private string _common;
    /// <summary>
    /// Common property
    /// </summary>
    public string CommonProperty
    {
        get { return _common; }
        set
        {
            _common = value;
            SetProperty(ref _common, value);
        }
    }  
}

My problem is: when I set the common property in the constructor, works fine. But when I´m setting the common property in OnNavigatingTo and using async, doesn´t work. The SetProperty is triggered when calling the OnNavigatingTo, but my binded label with this common property doesn´t refresh the value.

namespace TaskMobile.ViewModels.Tasks
{
/// <summary>
/// Specific view model
/// </summary>
public class AssignedViewModel : BaseViewModel, INavigatingAware
{


    public AssignedViewModel(INavigationService navigationService, IPageDialogService dialogService) : base(navigationService,dialogService)
    {
        CommonProperty= "Jorge Tinoco";  // This works
    }

    public async void OnNavigatingTo(NavigationParameters parameters)
    {
        try
        {
            Models.Vehicle Current = await App.SettingsInDb.CurrentVehicle();
            CommonProperty= Current.NameToShow; //This doesn´t works
        }
        catch (Exception e)
        {
            App.LogToDb.Error(e);
        }
    }
}

Upvotes: 0

Views: 1071

Answers (2)

Mahdi Asgari
Mahdi Asgari

Reputation: 292

when you use SetProperty, you should not set value for the backfield. so you should remove this line:

_common = value;

Upvotes: 1

Nkosi
Nkosi

Reputation: 247551

Because you are doing asynchronous invocation on a separate thread the UI is not being notified of the change.

The async void of OnNavigatingTo, which is not an event handler, means it is a fire and forget function running in a separate thread.

Reference Async/Await - Best Practices in Asynchronous Programming

Create a proper event and asynchronous event handler to perform your asynchronous operations there

For example

public class AssignedViewModel : BaseViewModel, INavigatingAware {
    public AssignedViewModel(INavigationService navigationService, IPageDialogService dialogService) 
        : base(navigationService, dialogService) {
        //Subscribe to event
        this.navigatedTo += onNavigated;
    }

    public void OnNavigatingTo(NavigationParameters parameters) {
        navigatedTo(this, EventArgs.Empty); //Raise event
    }

    private event EventHandler navigatedTo = degelate { };
    private async void onNavigated(object sender, EventArgs args) {
        try {
            Models.Vehicle Current = await App.SettingsInDb.CurrentVehicle();
            CommonProperty = Current.NameToShow; //On UI Thread
        } catch (Exception e) {
            App.LogToDb.Error(e);
        }
    }
}

That way when the awaited operation is completed the code will continue on the UI thread and it will get the property changed notification.

Upvotes: 1

Related Questions