Как повысить свойство, измененное в производных классах? - PullRequest
0 голосов
/ 20 февраля 2019

Как мне повысить PropertyChanged для SomeProperty в классе B?

Этот пример не компилируется, поскольку PropertyChanged недоступен таким образом ...

public class A : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
}

public class B : A
{
    private object _someProperty;

    public object SomeProperty
    {
        get => _someProperty;
        set
        {
            _someProperty = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SomeProperty)))
        }
    }
}

1 Ответ

0 голосов
/ 20 февраля 2019

Решение 1:

Вы можете использовать это RaisePropertyChangedExtension:

public static class RaisePropertyChangedExtension
{
    public static void RaisePropertyChanged(this INotifyPropertyChanged @this, [CallerMemberName] string propertyName = null)
    {
        var declaringType = @this.GetType().GetEvent(nameof(INotifyPropertyChanged.PropertyChanged)).DeclaringType;
        var propertyChangedFieldInfo = declaringType.GetField(nameof(INotifyPropertyChanged.PropertyChanged), BindingFlags.Instance | BindingFlags.NonPublic);
        var propertyChangedEventHandler = propertyChangedFieldInfo.GetValue(@this) as PropertyChangedEventHandler;
        propertyChangedEventHandler?.Invoke(@this, new PropertyChangedEventArgs(propertyName));
    }
}

Вот так:

public class B : A
{
    private object _someProperty;

    public object SomeProperty
    {
        get => _someProperty;
        set
        {
            _someProperty = value;
            this.RaisePropertyChanged();
        }
    }
}

На мой взгляд, это лучшее решение, которое язнаю пока.

Недостатком является то, что вы можете поднять PropertyChanged из другого класса, подобного этому:

public class C
{
    public C(B b)
    {
        b.RaisePropertyChanged(nameof(b.SomeProperty));
    }
}

Не рекомендуется поднимать PropertyChanged из других классовКстати, меня этот недостаток не беспокоит.

Это решение вдохновлено ответом Томаса Левеска здесь: Простая маленькая реализация INotifyPropertyChanged

Решение 2:

Вы можете создать защищенный RaisePropertyChanged в базовом классе A:

public class A : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

И вызвать метод в производном классеB:

public class B : A
{
    private object _someProperty;

    public object SomeProperty
    {
        get => _someProperty;
        set
        {
            _someProperty = value;
            RaisePropertyChanged();
        }
    }
}

Недостатком является то, что вы должны реализовывать метод RaisePropertyChanged для каждого нового базового класса, который вы создаете, напротив, вы избегаете недостатка, что Solution 1 был.

...