CommunityToolkit / dotnet

.NET Community Toolkit is a collection of helpers and APIs that work for all .NET developers and are agnostic of any specific UI platform. The toolkit is maintained and published by Microsoft, and part of the .NET Foundation.

Home Page:https://docs.microsoft.com/dotnet/communitytoolkit/?WT.mc_id=dotnet-0000-bramin

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add support for custom callback method in ObservableProperty

hailstorm75 opened this issue · comments

Overview

Assume that you are developing an observable model of a setting that contains a set of fields, decorated by the ObservableProperty attribute:

[ObservableObject]
public sealed partial class MyModel
{
  [ObservableProperty] private string _myField = string.Empty;
}

Assuming that this is a setting, other parts of the application might need to know when this setting is modified, i.e., it becomes dirty.
This is easily achieved using Messaging; however, it would require the developer to manually convert this field to a property with a backing field, defeating the purpose of the ObservableProperty attribute:

[ObservableObject]
public sealed partial class MyModel
{
  private string _myField = string.Empty;

  public string MyField
  {
    get => _myField;
    set
    {
      if (SetProperty(ref _myField, value))
        WeakReferenceMessenger.Default.Send(new SettingsChangedMessage(value, nameof(MyModel)));
    }
  }
}

I believe an additional attribute that allows the developer to specify a callback method to be executed once the property is changed or even retrieved would be beneficial.

API breakdown

I'm not familiar enough with IIncrementalGenerator and the current CommunityToolkit.MVVM implementation to provide a useful API breakdown.

However, I believe the generated code could utilize the SetPropertyAndNotifyOnCompletion method.

Usage example

public sealed partial class MyObservableClass : ObservableObject
{
  [ObservableProperty(CallbackSet = nameof(CustomSetCallback))] private string m_userEmail;

  private void CustomSetCallback(object oldValue, object newValue)
  {
    // TODO
  }
}

Breaking change?

I'm not sure

Alternatives

Currently, I've reserved to implement a custom generator using ISourceGenerator that finds an ObservablePropertyEx attribute to generate the necessary code with callback support.

Additional context

No response

Help us help you

No, just wanted to propose this

commented

I would like to have this feature too! Sometimes I have to reload some properties when another property has changed. A callback method within the setter would be great for this.

+1 on this
I thinks this could be helpful also for those cases where we want to trigger the same callback for multiple properties OnChanged events.

Right now we have to do something like this:

[ObservableProperty]
private bool _propertyA;
partial void OnPropertyAChanged(bool value) => DoStuff();

[ObservableProperty]
private bool _propertyB;
partial void OnPropertyBChanged(bool value) => DoStuff();

[ObservableProperty]
private bool _propertyC;
partial void OnPropertyCChanged(bool value) => DoStuff();

private void DoStuff()
{
    // do stuff here
}

With the proposed feature we could simplify, like this:

[ObservableProperty(CallbackSet = nameof(DoStuff))]
private bool _propertyA;

[ObservableProperty(CallbackSet = nameof(DoStuff))]
private bool _propertyB;

[ObservableProperty(CallbackSet = nameof(DoStuff))]
private bool _propertyC;

private void DoStuff()
{
    // do stuff here
}