It just calls InvalidateArrange() on the parent when the property change. This causes WPF to later call Arrange() on the parent. Neither of these calls has any way to intercept it (without using really sneaky techniques like patching IL code or attaching a debugger to the process).
This means that the only ways to write managed code that can detect the InvalidateArrange() is to create a custom parent which overrides the ArrangeOverride method, or tap into some behavior of the Arrange method for the particular control in question - for example if the parent is a Panel you could add an extra invisible child just to receive Arrange() calls from its parent.
Update When you get the Arrange() callback you cannot detect why InvalidateArrange() was called on the parent, but you can detect whether the property with the AffectsParentArrange flag has changed or not by saving the old value of the property in each Arrange call and comparing it to the previously saved value. This can be extended to multiple properties using a loop, a Dictionary, and either a list of properties or a call to GetLocalValueEnumerator().