【问题标题】:DataBinding on Getter Only Property That Concats 2 variables连接 2 个变量的 Getter Only 属性上的 DataBinding
【发布时间】:2017-10-30 08:36:21
【问题描述】:

我有以下课程

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 中绑定到 FullNameFullName_LastNameFirst 属性,当它们包装的任何一个属性发生更改时,我如何让它们更新。

【问题讨论】:

    标签: c# wpf mvvm inotifypropertychanged


    【解决方案1】:

    当您更改底层私有字段(firstNamelastNamename in BusinessContact)时 - 调用

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

    WPF 数据绑定将订阅您的对象的PropertyChanged 事件,并会监听相应属性的更改通知。由于您的属性没有可以调用 OnPropertyChanged 的设置器 - 当任何基础数据发生更改时,您需要显式调用它。

    【讨论】:

      【解决方案2】:

      你肯定有你的 Person 的属性。如果你有 ForeName 属性,你可以像这样实现它:

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

      如您所见,如果 ForeName 的值发生更改,将触发 PropertyChanged 事件。您可以使 LastName 属性相似。

      另一个解决方案是,如果 person 类监听它自己的 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));
          }
      }
      

      如果您已生成类,并且您无法更改属性设置器,则第二种解决方案很有用。然后你可以创建一个部分类,并处理属性更改。

      【讨论】:

        【解决方案3】:

        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 是我的一个例外。

        【讨论】:

          猜你喜欢
          • 2020-06-16
          • 1970-01-01
          • 1970-01-01
          • 2020-06-23
          • 2019-03-30
          • 1970-01-01
          • 2015-12-05
          • 2011-09-07
          • 2021-11-27
          相关资源
          最近更新 更多