'Winforms INotifyPropertyChanged: changes initiating in inner object do not update bound controls

I have an outer object that contains some basic string properties and a BindingList of inner objects.

Both outerclass and innerclass implement INotifyPropertyChanged and have a bool Dirty property that raises PropertyChanged. Furthermore, outerclass subscribes to the PropertyChanged of every child in a foreach loop, so that outer can self-dirty when any of its children get an "IsExcluded" bool property set.

I am binding the Enabled property of the Save button to the Dirty property of the BindingSource (see details at bottom).

Changes to the outer object enable the save button. Changes to any inner object do not enable the save button.

In both cases, I can see debug messages verifying the Dirty flags are correctly being set:

Case 1:
outer -- Dirty: True       (I edited a text field during the screen capture)
Case 2:
outer -- Dirty: True        (I clicked on 
inner -- Dirty: True        two checkboxes
inner -- Dirty: True        during the screen capture)

Screen capture of problem

Potentially relevant details:

  • At form create time, the BindingSource's DataSource is set to typeof(outerclass).
  • At edit time, I am holding a reference to the original outer object, then new-ing up a throwaway copy of the outer object through a copy constructor and setting the BindingSource's DataSource to this throwaway object. I set the BindingSource's DataSource back to the original outer if the user cancels.
  • In the debugger, the PropertyChanged delegate displays as null for the outer object's Dirty setter. Yet, as demonstrated in the screen capture, outer, or BindingSource, is somehow(?) triggering the Save button to enable itself regardless. The PropertyChanged delegate of inner correctly displays the expected listening method from outer.

EDIT 1: Minimal repro project: https://github.com/amonroejj/stack-overflow-71328541/tree/main



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source