DataBinding на свойстве Getter Only, которое объединяет 2 переменные

У меня следующие классы

public abstract class Contact 
{
    public abstract string FullName { get; }
    public abstract string FullName_LastNameFirst { get; }
}

public class PersonContact
{
    private string firstName;
    private string lastName;

    public override string FullName => firstName + " " + lastName;
    public override string FullName_LastNameFirst => lastName + ", " + firstName;
}

public class BusinessContact 
{
    private string name;

    public override string FullName => name;
    public override string FullName_LastNameFirst => name;
}

Эти классы расширяют INotifyPropertyChanged (не показаны) и включают общедоступные свойства, охватывающие частные переменные, запускающие OnPropertyChanged.

Вопрос в том, привязываю ли я в WPF к свойствам FullName или FullName_LastNameFirst, как я могу обновить их, когда любое из свойств, которые они обертывают, изменяется.


person yitzih    schedule 30.10.2017    source источник


Ответы (3)


Когда вы меняете базовые частные поля (firstName, lastName или name в BusinessContact) - вызовите

OnPropertyChanged("FullName"); 
OnPropertyChanged("FullName_LastNameFirst");

Связывание данных WPF будет подписываться на событие PropertyChanged вашего объекта и будет прослушивать уведомления об изменении соответствующего свойства. Поскольку у вашего свойства нет сеттера, в котором вы можете вызвать OnPropertyChanged, вам нужно вызывать его явно при изменении любых базовых данных.

person Evk    schedule 30.10.2017

У вас наверняка есть свойства для вашей личности. Если у вас есть свойство ForeName, вы можете реализовать его следующим образом:

private string _ForeName;

public string ForeName
{
    get
    { return _ForeName; }
    set
    {
        if (_ForeName != value)
        {
            _ForeName = value;
            OnPropertyChanged(nameof(this.ForeName));
            OnPropertyChanged(nameof(this.FullName));
        }
    }
}

Как видите, событие PropertyChanged будет запущено, если значение ForeName изменится. Вы можете сделать свойство LastName аналогичным.

Другое решение, если класс человека слушает свой собственный PropertyChanged:

public Person()
{
    this.PropertyChanged += this.Person_PropertyChanged;
}

private void Person_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == nameof(LastName))
    {
        this.OnPropertyChanged(nameof(FullName));
    }
    if (e.PropertyName == nameof(ForeName))
    {
        this.OnPropertyChanged(nameof(FullName));
    }
}

Это второе решение полезно, если вы сгенерировали классы и не можете изменять средства задания свойств. Затем вы можете создать частичный класс и обработать изменения свойств.

person lvoros    schedule 30.10.2017

Ответы Evk и lvoros технически верны.

Однако вы можете избавить себя от необходимости писать весь этот шаблонный код, используя библиотеку Fody ProperyChanged (доступна через Nuget).

Класс, записанный как

public class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string GivenNames { get; set; }
    public string FamilyName { get; set; }
    public string FullName => $"{GivenNames} {FamilyName}";
}

Фактически будет скомпилирован как

public class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    string givenNames;
    public string GivenNames
    {
        get => givenNames;
        set
        {
            if (value != givenNames)
            {
                givenNames = value;
                OnPropertyChanged("GivenNames");
                OnPropertyChanged("FullName");
            }
        }
    }

    string familyName;
    public string FamilyName
    {
        get => familyName;
        set 
        {
            if (value != familyName)
            {
                familyName = value;
                OnPropertyChanged("FamilyName");
                OnPropertyChanged("FullName");
            }
        }
    }

    public string FullName => $"{GivenNames} {FamilyName}";

    public virtual void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Fody будет автоматически генерировать вызовы OnPropertyChanged () для любых зависимых вычисляемых свойств в дополнение к прямым оболочкам свойств.

Обычно я не фанат программ, работающих «по волшебству», но Fody - мое единственное исключение.

person Peregrine    schedule 30.10.2017