dotnet icon indicating copy to clipboard operation
dotnet copied to clipboard

NewPropertyChangedEvent on ObservableObject

Open Hakoyu opened this issue 2 years ago • 0 comments

Overview

I want to get the old value and the new value in the event

API breakdown

namespace CommunityToolkit.Mvvm.ComponentModel;
public abstract class ObservableObject
{
    protected bool SetProperty<T>(
        [NotNullIfNotNull(nameof(newValue))] ref T field,
        T newValue,
        [CallerMemberName] string? propertyName = null
    )
    {
        if (EqualityComparer<T>.Default.Equals(field, newValue))
        {
            return false;
        }
        
        OnPropertyChanging(propertyName);
        
        var oldValue = field;
        if (AnotherPropertyChanging is not null)
            AnotherPropertyChanging?.Invoke(this, new(propertyName, oldValue, newValue));

        field = newValue;

        OnPropertyChanged(propertyName);

        if (AnotherPropertyChanged is not null)
            AnotherPropertyChanged?.Invoke(this, new(propertyName, oldValue, newValue));

        return true;
    }

    public event AnotherPropertyChangingEventHandler? AnotherPropertyChanging;
    public event AnotherPropertyChangedEventHandler? AnotherPropertyChanged;
}

public delegate void AnotherPropertyChangingEventHandler(
    object sender,
    AnotherPropertyChangingEventArgs e
);
public delegate void AnotherPropertyChangedEventHandler(
    object sender,
    AnotherPropertyChangedEventArgs e
);

public class AnotherPropertyChangingEventArgs : PropertyChangingEventArgs
{
    public object? OldValue { get; }

    public object? NewValue { get; }

    public AnotherPropertyChangingEventArgs(
        string? propertyName,
        object? oldValue,
        object? newValue
    )
        : base(propertyName)
    {
        OldValue = oldValue;
        NewValue = newValue;
    }
}

public class AnotherPropertyChangedEventArgs : PropertyChangedEventArgs
{
    public object? OldValue { get; }

    public object? NewValue { get; }

    public AnotherPropertyChangedEventArgs(string? propertyName, object? oldValue, object? newValue)
        : base(propertyName)
    {
        OldValue = oldValue;
        NewValue = newValue;
    }
}

Usage example

public partial class MainWindowViewModel : ObservableObject
{
    AnotherViewModel anotherViewModel = new();

    [ObservableProperty]
    private int _oldValue = 0;

    [ObservableProperty]
    private int _newValue = 0;

    public MainWindowViewModel()
    {
        anotherViewModel.AnotherPropertyChanged += (s, e) =>
        {
            if (e.PropertyName == nameof(AnotherViewModel .Value))
            {
                OldValue = e.OldValue;
                NewValue = e.NewValue;
            }
        };
    }
}

public partial class AnotherViewModel : ObservableObject
{
    [ObservableProperty]
    private int _value = 0;
}

Breaking change?

No

Alternatives

Currently I'm using reflection to get the old value, but that's a very bad.

protected override void OnPropertyChanging(PropertyChangingEventArgs e)
{
    base.OnPropertyChanging(e);
    if (AnotherPropertyChanged is not null)
    {
        _oldValue = this.GetType().GetProperty(propertyName).GetValue(this);
    }
}

Additional context

No response

Help us help you

Yes, I'd like to be assigned to work on this item

Hakoyu avatar Nov 24 '23 09:11 Hakoyu