【问题标题】:Again, ObservableCollection doesnt Update item同样, ObservableCollection 不会更新项目
【发布时间】:2013-06-17 13:47:35
【问题描述】:

那是我第一个使用 MVVM 的项目,MVVM light。 我有一个列表框,它从 PersonList Observable 集合中刷新,正常添加和删除刷新。问题出在编辑项目时。

我为这个问题寻找了所有解决方案,但没有任何效果,这让我觉得我错过了一些东西。

所以这里是代码:

 public class AdminViewModel : ApplicationPartBaseViewModel
{
   private ObservableCollection<Person> personList;

   public AdminViewModel()
    {

       this.context = new Entities();
       this.SavePersonCommand = new RelayCommand(() => this.SavePerson ());


       this.PersonList = new ObservableCollection<Peson>(context.Person.OrderBy(o => o.PersonName).ToList());


     }

      public ObservableCollection<Person> PersonList
    {
        get
        {
             return personList;
        }

        set
        {
            this.personList = value;
            RaisePropertyChanged("PersonList");
        }
    }


     private void SavePerson()
    {
      //Add and update code here
       this.context.SaveChanges();
       RaisePropertyChanged("PersonList");



    }


}

Person 类是从 DataModel edmx 自动生成的模板

 //------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

public partial class Person 
{
    #region Primitive Properties

    public virtual int PersonId
    {
        get;
        set;
    }

    public virtual string PersonName
    {
        get;
        set;
    }

    public virtual Nullable<int> PersonAge
    {
        get;
        set;
    }

    #endregion
    #region Navigation Properties

    public virtual ICollection<Humans> Humans
    {
        get
        {
            if (_human == null)
            {
                var newCollection = new FixupCollection<Human>();
                newCollection.CollectionChanged += FixupHuman;
                _human = newCollection;
            }
            return _human;
        }
        set
        {
            if (!ReferenceEquals(_human, value))
            {
                var previousValue = _human as FixupCollection<Human>;
                if (previousValue != null)
                {
                    previousValue.CollectionChanged -= FixupHuman;
                }
                _human = value;
                var newValue = value as FixupCollection<Human>;
                if (newValue != null)
                {
                    newValue.CollectionChanged += FixupAssets;
                }
            }
        }
    }
    private ICollection<Human> _human;

    #endregion
    #region Association Fixup

    private void FixupHuman(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach (Human item in e.NewItems)
            {
                if (!item.Person.Contains(this))
                {
                    item.Person.Add(this);
                }
            }
        }

        if (e.OldItems != null)
        {
            foreach (Human item in e.OldItems)
            {
                if (item.Person.Contains(this))
                {
                    item.Person.Remove(this);
                }
            }
        }
    }

    #endregion
}

我认为当我调用 RaisePropertyChanged 时 MVVM 灯会更新项目。 我感到很困惑。

提前致谢。

【问题讨论】:

  • ObservableCollection&lt;T&gt; 中的项目必须自己实现 INPC,以便您的“编辑”更改传播到 UI。
  • 当我尝试实现它时,它说它已经在 mvvm light 中实现了。我应该使用覆盖或新的关键字。
  • 请贴出Person类代码
  • 你的 Person 类与 mvvm light 应该看起来像 public class Person : ObservableObject {...} 并且你应该在它的属性上调用 RaisePropertyChanged(...)。这不能在AdminViewModel 类中完成。现在有了这个“实现”,如果您在AdminViewModel 中修改Person 的对象,您将看到更改反映在您的视图中
  • 如果引用没有改变,不要提升 PersonList。 INotifyPropertyChanged 和 INotifyCollectionChanged 的​​全部原因是告诉 WPF 究竟发生了什么变化。第一个用于属性更改,第二个用于添加,删除等集合更改。当然,可观察列表中的元素再次需要使用 INotifyPropertyChanged,这与可观察的集合无关,只是通知修改集合本身。

标签: wpf mvvm


【解决方案1】:

如果可以的话,第一个选项是尝试让你的自动生成的类来实现 INPC。看看Fody.PropertyChanged

如果这不可能,因为它确实具有“虚拟”属性,我们可以在派生类中覆盖它们,例如

public class ObservablePerson : Person, INotifyPropertyChanged {
  public override int PersonId {
    get {
      return base.PersonId;
    }
    set {
      base.PersonId = value;
      OnPropertyChanged();
    }
  }

  public override string PersonName {
    get {
      return base.PersonName;
    }
    set {
      base.PersonName = value;
      OnPropertyChanged();
    }
  }

  public override int? PersonAge {
    get {
      return base.PersonAge;
    }
    set {
      base.PersonAge = value;
      OnPropertyChanged();
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  [NotifyPropertyChangedInvocator]
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
      handler(this, new PropertyChangedEventArgs(propertyName));
  }
}

现在在您的AdminViewModel 中使用ObservablePerson 类型的对象而不是Person

【讨论】:

  • 幸运的是,这个 MVVM light 实现了所有类的 INPC,所以我做了第一个选择(不需要 Fody)。非常非常感谢:)
猜你喜欢
  • 2014-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-23
  • 2010-11-24
  • 2021-11-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多