0
votes

I am writing a Windows 8.1 Store App in C#, MVVM Pattern.

I have 3 ViewModels: 1. BaseViewModel 2. StudentViewModel 3. StudentDashboardViewModel

Its like:

  • I added BaseViewModel.
  • I inherited StudentViewModel from BaseViewModel.
  • Then, I inherited StudentDashboardViewModel from StudentViewModel.

I made a Page StudentDashboardPage and I binded it to StudentDashboardViewModel.

I am trying to change a property example, IsBlackIn in StudentViewModel via another class but the problem is that it is not notifying its child viewmodel StudentDashboardViewModel.

So, how to notify child viewmodel of changes in parent viewmodel. Here is the code:

BaseViewModel:

 public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
        {
            if (Object.Equals(storage, value))
            {
                return false;
            }
            storage = value;
            this.OnPropertyChanged(propertyName);
            return true;
        }
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var eventHandler = this.PropertyChanged;
            if (eventHandler != null)
            {
                eventHandler(this, new PropertyChangedEventArgs(propertyName));
            }
        }            
    }

StudentViewModel:

 public class StudentViewModel : BaseViewModel
    {    
        private static StudentViewModel studentViewModel;            
        public static StudentViewModel Singleton()
        {
            if (studentViewModel == null)
            {
                studentViewModel = new StudentViewModel();
            }
            return studentViewModel;
        } 

        private bool _IsBlackIn = false;
        public bool IsBlackIn
        {
            get { return _IsBlackIn; }
            set
            {
                SetProperty<bool>(ref _IsBlackIn, value);               
            }
        }   
    }

StudentDashboardViewModel:

public class StudentDashboardViewModel : StudentViewModel
{
    public static StudentDashboardViewModel studentDashboardViewModel;

    public static StudentDashboardViewModel GetSingleInstance()
    {
        return studentDashboardViewModel ?? (studentDashboardViewModel = new StudentDashboardViewModel());
    }

}

StudentDashboardPage page behind code:

public sealed partial class StudentDashboardPage : Page
{
    private StudentDashboardViewModel studentDashvm;

    public StudentDashboardPage()
    {
        this.InitializeComponent();         
        this.Loaded += StudentDashboardPage_Loaded;
    }

    private void StudentDashboardPage_Loaded(object sender, RoutedEventArgs e)
    {
        this.studentDashvm = StudentDashboardViewModel.GetSingleInstance();
        this.DataContext = studentDashvm;
    }   
}
1
Back to MVVM fundamentals. Why are your ViewModels singleton in first place? ViewModel is supposed to be alive only as long as the corresponding View is displayed and not throughout the application lifespan. - Nikhil Vartak
I am planning to revert back from singleton but, what about Notify problem? - Atif Shabeer
View-models can outlive their views and even be shared by multiple views, but I agree that they shouldn't be singletons. - Jonathan Allen
If you change property's value in base class once the derived class is binded to the UI, its value will not reflect in the UI. so you do it in the dervied class i.e. in StudentDashboardViewModel class. And i agree this is not a good practice to use ViewModels as singleton. - Vivek Saurav

1 Answers

2
votes

There are 3 ways i can see the StudentDashboardViewModel can get notified of any change that can occur to the IsBlackIn property defined in StudentViewModel:

  1. Make SetProperty<T> (in BaseViewModel) virtual and override in StudentDashboardViewModel and check the name of the property.
  2. Make the setter of the IsBlackIn property in StudentViewModel virtual and override in StudentDashboardViewModel.

In the previous two cases don't forget to call the base method whether that was SetProperty<T> or IsBlackIn setter.

The third option you have is to compose the view models (use composition over inheritance). That is, let StudentDashboardViewModel receive an instance of StudentViewModel and then listen to an event that notifies the change of IsBlackIn. You can either listen to INotifyPropertyChanged.PropertyChanged or implement your own custom event.