0
 private ObservableCollection<Employee> models = new ObservableCollection<Employee>();

My model has 2 fields (Name and a boolean field called activeDuty)

In my constructor, I

 this.models.CollectionChanged += this.OnCollectionChanged;


void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)

I've never used an ObservableCollection, could someone tell me how I would detect if the activeDuty field was modified?(I did some digging and saw many posts about OnCollectionChanged and OnItemPropertyChanged but didnt understand the difference or why one is preferred over another

software is fun
  • 7,286
  • 18
  • 71
  • 129
  • You can use the `.CollectionChanged` like [this](https://dotnetfiddle.net/36O4hv). This event "Occurs when an item is added, removed, changed, moved, or the entire list is refreshed". – David Pine Apr 26 '16 at 19:42
  • Both this question and especially the accepted answer are simpler and easier to read than those of the marked duplicate – binaryfunt Mar 14 '18 at 01:09

1 Answers1

6

ObservableCollection.CollectionChanged is raised when an item is added to, or removed from, the collection. ObservableCollection also implements INotifyPropertyChanged, only to raise notifications for changes of its own personal properties -- and so will also raise a PropertyChanged event for its Count property when an item is added or removed (you've got zero reason to care about that right now, but we may as well toss it out there for what it's worth).

So: Your ObservableCollection of Employee won't raise any events when one of its containees has a property change, regardless of whether or not the containee implements INotifyPropertyChanged. The containee should implement INotifyPropertyChanged itself, and raise events when its own property values change -- but an ObservableCollection containing it won't listen for those events. We don't need to notify absolutely everybody about absolutely everything.

But you do need to know when activeDuty changes. Easy.

When you create new Employee instances, you could handle their PropertyChanged events with your OnItemPropertyChanged handler:

//  Fred's not what you'd call active.
var fred = new Employee { Name = "Fred", activeDuty = false };

fred.PropertyChanged += OnItemPropertyChanged;

models.Add(fred);

If Employee implements INotifyPropertyChanged correctly, any detectable increase in Fred's activity level will be perceived immediately in OnItemPropertyChanged. The object sender parameter will be Fred, and e.PropertyName will be the string "activeDuty".

public class Employee : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private bool _activeDuty = false;
    public bool activeDuty {
        get { return _activeDuty; }
        set {
            _activeDuty = value;
            PropertyChanged?.Invoke(this, 
                new PropertyChangedEventArgs(nameof(activeDuty)));
        }
    }

    //  Name implemented similarly -- either that, or give it a protected 
    //  setter and initialize it in the constructor, to prevent accidents.
}

I don't think you need to be handling models.CollectionChanged unless random other viewmodels could be adding to it. If they could be, then that's a very handy place to put PropertyChanged handlers on new Employees.

  • Makes a lot of sense. So instead of tracking the entire collection, I am tracking the specific record. When I implement your recommendation, the set property is only being executed when the item is Unchecked. – software is fun Apr 28 '16 at 13:42
  • @softwareisfun Right. The ItemsControl only cares about which items are in the collection. It hands over display of the items to the item template, each instance of which only cares about the properties of the item it has. – 15ee8f99-57ff-4f92-890c-b56153 Apr 28 '16 at 13:52
  • In my class, where I create the models. What code would go in OnItemPropertyChanged when we execute fred.PropertyChanged += OnItemPropertyChanged; – software is fun Apr 28 '16 at 14:15
  • @softwareisfun That depends on your goals. You could set a dirty flag on the Employee so you know it needs to be saved later, and/or set a dirty flag on the main viewmodel to indicate that something, somewhere, needs a save. If the dirty flags raise `PropertyChanged`, the UI could indicate visually that a save is needed; on application close, you can check the main dirty flag and prompt for a save, or you could save automagically. Saving to a DB on every property change is likely to bog down the UI. – 15ee8f99-57ff-4f92-890c-b56153 Apr 28 '16 at 14:24
  • As long as it gets saved before the application exits. This is a very low use application for a very specific need. I dont anticipate someone unchecking/checking the active boxes very often – software is fun Apr 28 '16 at 14:25