0

For building the WPF application I used VS2022 (V17.4.4) and NuGet Fody.PropertyChanged Package (V4.1.0).

If a property is set directly, the PropertyChanged event will be raised for the property itself and all the [DependsOn] properties as well. But if only the underlying field of the property is set and the PropertyChanged event is raised later manually by call of RaisePropertyChanged(nameof(Property)) the [DependsOn] properties will not raise any PropertyChanged event.

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace FodyPropertyChanged
{
  [PropertyChanged.AddINotifyPropertyChangedInterface]
  public class MainWindowViewModel : INotifyPropertyChanged
  {
    private DeviceStates _DeviceState;
    private event PropertyChangedEventHandler _propertyChanged;
    
    
    public event PropertyChangedEventHandler PropertyChanged
    {
      add { _propertyChanged += value; }
      remove
      {
        if (_propertyChanged != null)
          _propertyChanged -= value;
      }
    }

    public DeviceStates DeviceState
    {
      get { return _DeviceState; }
      set { _DeviceState = value; }
    }

    [PropertyChanged.DependsOn(nameof(DeviceState))]
    public bool IsBusy
    {
      get { return DeviceState == DeviceStates.Working; }
    }

    public void SetDeviceStateTo(DeviceStates deviceState)
    {
      DeviceState = deviceState;
    }

    public void SetDeviceStateToAndRaisePropertyChangedAfterwards(DeviceStates deviceState)
    {
      _DeviceState = deviceState;

      RaisePropertyChanged(nameof(DeviceState));
    }

    private void RaisePropertyChanged([CallerMemberName] string propertyName = "")
    {
      PropertyChangedEventHandler handler = _propertyChanged;
      if (handler != null)
      {
        handler(this, new PropertyChangedEventArgs(propertyName));
      }
    }
  }
}

If I call SetDeviceStateTo(...) the PropertyChanged event will be raised for DeviceState and IsBusy (GUI will be updated, correctly). But if I call SetDeviceStateToAndRaisePropertyChangedAfterwards(...) the PropertyChanged event will be raised for DeviceState, only (IsBusy bindings will not be updated).

Any idea?

jauchand
  • 17
  • 4
  • 2
    Well, yes. Fody rewrites the property setter to raise events for DependsOn properties. If you don't call the property setter, this code isn't run – canton7 Feb 14 '23 at 10:31
  • Why are you not just setting the property? – Andy Feb 14 '23 at 10:52
  • Sometimes I want to set only the property without updating the GUI at this point. The update of the GUI will be done later (depending on some other stuff) by calling RaisePropertyChanged for some properties. – jauchand Feb 14 '23 at 11:56
  • Calling `RaisePropertyChanged(nameof(DeviceState));` simply raises the PropertyChanged event and does nothing else. You should know this because you have implemented this method. Fody does not listen to any events. It's a plain code generator that generates code during compilation. `DependsOn` just generates another event invocation in the setter for the decorated property. Simply don't use code generation for such trivial but important tasks. You lose some valuable control and eliminate your possibilities. Especially as a beginner you should avoid such code generators. That's just my opinion. – BionicCode Feb 14 '23 at 12:15
  • Or don't use properties (property setters) to implement logic. Properties aremeant primarily to store the object's state. Methods are meant to implement logic i.e. methods "do" something. You can simply create a wrapper method that sets all related properties together. The latter is also far easier to read in order to understand what's going on. – BionicCode Feb 14 '23 at 12:15
  • All right, I see. [DependsOn] is only working for the setter not for events. So it is a known limitation and not a bug. Thanks for clarification. – jauchand Feb 14 '23 at 12:28

1 Answers1

0

Like canton7 and BionicCode said: [DependsOn] is only working for the setter not for events. So it is a known limitation and not a bug.

jauchand
  • 17
  • 4
  • I wouldn't call it a limitation. It's simply not how the library works. It's only a *code generator* that injects code during the build process. For example, it creates an inline method `OnPropertyChanged()` for the current class. Then it will inject a method call to this method into every property `set()` to raise the `PropertyChanged` event for the actual property. If the property is decorated with the `DependsOn` attribute, Fody will inject a `OnPropertyChanged` call for the decorated property into the `set()` of the dependent property. Only code generation of `OnPropertyChanged` calls. – BionicCode Feb 14 '23 at 13:20
  • Regarding your provided example, a simple fix would be to set the `DeviceState` property just before returning from the `SetDeviceStateToAndRaisePropertyChangedAfterwards` method (at the end of the method) and everything will behave as you expect it to. This way you eliminate the explicit `RaisePropertyChanged` call and allow the property to do its job of cascading the PropertyChanged notifications. – BionicCode Feb 14 '23 at 13:20
  • To observe the `PropertyChanged` event and take actions based on the `DependsOn` attribute configuration is very very easy to implement by yourself. You can even reuse it for other classes. – BionicCode Feb 14 '23 at 13:29