Search code examples
c#wpfobservablecollection

Using different instances of a ViewModel class can cause problems updating an ObservableCollection?


I have a BookViewModel class with some properties, one of then an ObservableCollection. But I'm having problems updating its value. This is my case:

public class BookViewModel : INotifyPropertyChanged
    {

        private IEnumerable<Book> booksList;

        private ObservableCollection<Chapter> selectedChapters = new ObservableCollection<Chapter>();

        public BookViewModel()
        {
        }

        public BookViewModel(List<Book> booksList)
        {
            this.BooksList = booksList;
        }

    // ...

    public ObservableCollection<Book> SelectedChapters
        {
            get
            {
                return this.selectedChapters;
            }

            set
            {
                this.selectedChapters = value;
                this.OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
}

In one UserControl of my application I do:

private TrainViewModel booksViewModel;
// ...
booksViewModel = new BookViewModel(booksList);  // booksList comes from other site
this.DataContext = this.booksViewModel;

And in another UserControl, which is created dynamically as a child of the previous UserControl, I do:

private TrainViewModel booksViewModel;
// ...
booksViewModel = new BookViewModel();
this.DataContext = this.booksViewModel; // Different constructor

In this latter page, I have some checkboxes which modify my selectedChapters property by adding or removing elements from it:

// When some checkbox is checked
this.booksViewModel.SelectedChapters.Add(selectedChapter);
// When some checkbox is unchecked
this.booksViewModel.SelectedChapters.Remove(selectedChapter);

If each time a checkbox is checked or unchecked I do:

Debug.Print(this.booksViewModel.SelectedChapters.Count());  // Always print out 1!!

I'm wondering if using the same ViewModel, but with different instances in each view (the new thing), is causing the problem.


Solution

  • Ok, I could solve it. Not sure if I'm expressing myself well, but it was like I was modifying different sources of data (i.e. data contexts). So, what I did was try to cast the data context of the child UserControl to a BookViewModel (which is the data context of its parent) and work from that:

    // Inside the event handler for check and uncheck
    BookViewModel bookViewModel = this.DataContext as BookViewModel;
    
    // When some checkbox is checked
    if (bookViewModel != null){
        this.booksViewModel.SelectedChapters.Add(selectedChapter);
    }
    
    // When some checkbox is unchecked
    if (bookViewModel != null){
        this.booksViewModel.SelectedChapters.Remove(selectedChapter);
    }
    

    And that's all. Update perfectly. I don't do anything with related to data dontext or view model in any part of the code (even in the constructor). Now, it's like I'm modifying the data in the same data context of the parent (sorry if my explanation isn't precise, I'm still getting used to WPF concepts).