How to Call Methods in the Setter Property of [ObservableProperty] in CommunityToolkit.MVVM?

269 views Asked by At

I’m using the CommunityToolkit.MVVM in my MainViewModel to reduce boilerplate code. However, I’m having trouble calling methods within the setter property of an [ObservableProperty].

Previously, before migrating to source generators, I had a setter where I could call a method like so:

private string _person;
public string Person
{
    get { return _person; }
    set 
    { 
        SetProperty(ref _person, value);
        LoadPerson();
    }
}

private void LoadPerson()
{
    _person = "Hello";
}

After migrating to source generators and using [ObservableProperty], I’m unsure how to call the LoadPerson() method. Here’s my current code:

[ObservableProperty]
string person; // How can I call LoadPerson() here?

[RelayCommand]
private void LoadPerson()
{
    Person = "Hello World";
}

Any guidance on how to call methods within the setter property of an [ObservableProperty] would be greatly appreciated. Thanks in advance.

2

There are 2 answers

0
BionicCode On BEST ANSWER

You can always implement a full property. Especially for cases where the property set or get is executing additional code (beside from raising the INotifyPropertyChanged.PropertyChanged event), the Toolkit solution does not offer any advantage (aside from creating overhead by injecting loads of code). You finally end up writing boilerplate code too - this time you are doing it for a questionable library (but this is up for debate I guess).
Since there is code-completion and code-templates in Visual Studio, you don't have to type the code for a property. Simply type "prop" and hit the Tab key twice. Now you have the properties generated for you and are still in full control.

Alternatively, add some Toolkit "boilerplate code".
Toolkit injects a bunch of event invocators and pre- and post event methods when generating the actual property.
In your case this is e.g., OnPersonChanging (On[property_name]Changing) and OnPersonChanged. Since these are instance members, you can simply extend them by using the partial language feature and create a partial method:

[ObservableProperty]
string person;

partial void OnPersonChanged(string? oldValue, string? newValue)
  => LoadPerson();
2
Samivand On

In CommunityToolkit.MVVM, the [ObservableProperty] attribute is used to generate properties with the INotifyPropertyChanged implementation. However, it doesn't directly support calling methods in the setter like the traditional approach you had.

If you want to perform additional actions when the property changes, you can use the PropertyChanged event provided by the ObservableObject base class. Here's an example of how you can achieve this:

using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;

public class MainViewModel : ObservableObject
{
    private string _person;

    [ObservableProperty]
    public string Person
    {
        get { return _person; }
        set
        {
            SetProperty(ref _person, value);
            LoadPerson();
        }
    }

    private void LoadPerson()
    {
        // Additional logic when Person changes
        // You can also use the Person property here
        // e.g., string loadedPerson = Person;
    }

    [RelayCommand]
    private void LoadPersonCommand()
    {
        Person = "Hello World";
    }
}

In this example, the ObservableObject class provides the SetProperty method and the PropertyChanged event. The SetProperty method handles the property assignment and raises the PropertyChanged event. By overriding the setter of the property and calling the LoadPerson method after setting the value, you can achieve the desired behavior.

Note: If you are using the [RelayCommand] attribute for methods, make sure that the method name is suffixed with "Command." In this example, LoadPerson is associated with the LoadPersonCommand command.