Search code examples
c#wpfmvvmnotifications

How to notify my view model that an object inside an observable collection has changed


I have a simple ToggleableObject class that tracks on/off states and an ObservableCollection of that object in my view model.

I know how to trigger an event when an object is added/removed from the collection, but how do I know when objects inside the collection are changed (ideally passing the sender so I know which one)?

The ObservableObject that the ToggleableObject inherits is from CommunityToolkit.Mvvm.ComponentModel and implements INotifyPropertyChanged

XAML:

        <ItemsControl ItemsSource="{Binding ToggleButtons}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

View Model:

        public ObservableCollection<ToggleableObject> ToggleButtons { get; set; }
        
        public void DoSomethingIfAButtonIsToggled(object sender)
        {
            // do stuff...
        }

ToggleableObject:

    public class ToggleableObject : ObservableObject
    {
        public string Name { get; set; }
        public bool IsChecked { get; set; }
    }

Solution

  • If you need to implement tracking at the ViewModel level, then replace ObservableCollection with BindingList:

            public BindingList<ToggleableObject> ToggleButtons { get; } = new();
    
            public SomeVM()
            {
                ToggleButtons.ListChanged += DoSomethingIfAButtonIsToggled;
            }
    
            private void DoSomethingIfAButtonIsToggled(object? sender, ListChangedEventArgs e)
            {
                // do stuff...
            }
    

    I don't know your implementation of ObservableObject, and if you're using some .Net assembly post-processing package (like Fody), so I can't say for sure if you've implemented ToggleableObject correctly. With a large degree of probability, the implementation should be like this:

    public class ToggleableObject : ObservableObject
    {
        private string _name;
    
        public string Name
        {
            get => _name;
            set => SetProperty(ref _name, value);
        }
    
        private bool _isChecked;
    
        public bool IsChecked
        {
            get => _isChecked;
            set => SetProperty(ref _isChecked, value);
        }
    }