Search code examples
c#xamarinmvvmxamarin.formsviewmodel

Xamarin forms ViewModels Inheritance


I work on developing a Xamarin forms application about video games using MVVM for my pet project. I am new in Xamarin forms, I need your advice.

I had a few ViewModels with the same code in it. I decided to create one base ViewModel and inherit others from that.

I have ViewModelBase with PropertyChanged event:

 public class ViewModelBase : INotifyPropertyChanged
 {
    private string _title;
    public string Title
    {
        get => _title;
        set => Set(ref _title, value);
    }

  
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void Set<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        field = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
 
}

I also have a base GamesViewModel from which others are inherited, there is a lot of code, that is why I will show only that I inherit everything properly:

public class GamesViewModel : ViewModelBase

Below are derived ViewModels:

public class NewGamesViewModel : GamesViewModel

and

public class SearchViewModel : GamesViewModel

Problem is I have SearchGame property in the base GamesViewModel:

  private string _searchGame;
    public string SearchGame
    {
        get => _searchGame;
        set => Set(ref _searchGame, value);
    }

When the program is running I put the value inside SearchGame property,and in GamesViewModel I can see that value assigned, but in derived ViewModels value is null:

For example, in debugging in SearchViewModel which is inherited from the GamesViewModel I check the value and it's null.

var test = SearchGame; - value is null here

I don't create any object of GamesViewModel in the project.

In the pages Code-behind files in BindingContext I do like this:

public partial class SearchGamePage : ContentPage
{
    public SearchGamePage()
    {
        InitializeComponent();
        BindingContext = new SearchViewModel();
    }
}

I tried to explain as more as I can. Maybe in Xamarin forms inheritance with ViewModels work not obviously.

Thank you in advance for the help!

Have a nice day!


Solution

  • I sent a message to the GamesViewModel with search game value like this:

      MessagingCenter.Send(this, "search_game", titleViewModel.SearchGame);
      var detailPage = (Application.Current.MainPage as MasterDetailPage)?.Detail;
      await detailPage.Navigation?.PushAsync(new SearchGamePage());
    

    I subscribe to this message in GamesViewModel constructor and assigned to SearchGame property message value like this:

     MessagingCenter.Subscribe<CustomTitleView, string>(this, "search_game", (sender, message) =>
       {
                SearchGame = message;
        });
    

    But as you can see in the code above I create SearchGamePage instance. SearchGamePage constructor calls and I create in it new SearchViewModel instance:

    public partial class SearchGamePage : ContentPage
    {
        public SearchGamePage()
        {
            InitializeComponent();
            BindingContext = new SearchViewModel();
        }
    }
    

    That's why GamesViewModel constructor calls again and in SearchGame property assign null.

    I solved this problem using DependencyService.Register in App.xaml.cs file:

     public App()
        {
            InitializeComponent();
    
            DependencyService.Register<MockDataStore>();
            DependencyService.Register<IGameApiClient, GameApiClient>();
            DependencyService.Register<IFavoriteGameService, FavoriteGameService>();
            DependencyService.Register<GamesViewModel>();
            DependencyService.Register<SearchViewModel>();
            DependencyService.Register<NewGamesViewModel>();
            DependencyService.Register<TitleViewModel>();
            MainPage = new MainPage();
        }
    

    And finally, in SearchGamePage constructor I assign to BindingContext SearchViewModel like this:

     public SearchGamePage()
     {
            InitializeComponent();
            BindingContext = DependencyService.Get<SearchViewModel>();
     }
    

    Now everything is fine when I assign value to SearchGame property in GamesViewModel using messenger I can see the same value in the SearchGame property in SearchViewModel because this ViewModel wasn't recreated.

    I understand that I didn't give full info when I asked a question. But I hope that if somebody else will face the same problem this answer will be useful.