【问题标题】:ObservableCollection not notifying update (MVVM WPF GridView)ObservableCollection 不通知更新(MVVM WPF GridView)
【发布时间】:2014-07-14 15:08:12
【问题描述】:

我有一个问题,我有一个由“人”填充的 GridView

ObservableCollection<Person> People
{

    get { return directory.People }

    set { directory.People = value; } 
}

这是对 GridView 的完美更新,但我只想显示名称为“Andy”的人,因此我将其更改为以下内容:

ObservableCollection<Person> People
{
    get {

        var andys = new ObservableCollection<Person>();

        foreach (var person in directory.People)
        {
            if (person.Name == "Andy")
            {
                  andys.Add(person);
            }
        }

        return andys;
     }

     set { directory.People = value; } 

}

上面的代码将完美地填充 GridView,但如果我执行以下操作,它不会更新它

Private Void AddAndy()
{
    directory.People.Add(new Person{ name = Andy2 });
    //People.Add(new Person { name = Andy2 }); -- Doesn't work either
}

这意味着虽然 GridView 最初会填充,但任何其他更改都不会对 Grid 产生影响。我已经切换回直接查看 Directory.People,它会在添加人员时返回更新。

我检查了当我将这个人添加到“dirctory.People”时,它确实说列表中有一个新项目。

我可以做些什么来强制“People”变量识别出发生了变化,进而让 GridView 更新?

非常感谢,

安迪

【问题讨论】:

  • 您需要了解和实施INotifyPropertyChanged Interface
  • @AndyJones 每次获得价值时都会创建新列表。创建一个列表并添加/删除项目。
  • 在网格视图上使用过滤器,如stackoverflow.com/questions/5843537/…
  • 感谢您的回复(好吧,Will 并没有这么多,但有些人喜欢通过上网来充实他们的一天)。这有点困难,因为我刚刚继承了应用程序,所以我不愿意做出巨大的改变,但我看到了创建和删除项目 dkozl 的大问题,尽管我希望整个网格会刷新(如如果我添加和删除了许多项目)。我之前尝试过这个过滤器,但显然实际的应用程序要复杂得多(在帖子中将其简化),这使得它变得困难,但我想我会再次尝试这种方法。

标签: c# wpf gridview mvvm observablecollection


【解决方案1】:

简单地说,目录对象上的 People 属性与您在属性访问器中创建的 ObservableCollection 之间没有任何联系。

那么 XAML 框架如何知道 directory.People 集合何时更新?

我建议使用 ListCollectionView 并将其作为 ViewModel 上的属性公开,

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class PeoplesViewModel
{
    private ObservableCollection<Person> _people;
    private ListCollectionView _filteredPeople;

    public PeoplesViewModel()
    {
        _people = new ObservableCollection<Person>();
        _filteredPeople = new ListCollectionView(_people);

        _people.Add(new Person { FirstName = "John", LastName = "Smith" });
        _people.Add(new Person { FirstName = "David", LastName = "Smith" });
        _people.Add(new Person { FirstName = "John", LastName = "Jones" });

        _filteredPeople.Filter = x => ((Person) x).FirstName == "John";
    }

    public IEnumerable People { get { return _filteredPeople; } } 
}

现在当一个新的 Person 添加到 View 时会自动更新。

现在我意识到这与上面的略有不同,但如果 directory.People 是ObservableCollection&lt;T&gt; 那么这应该可以工作。

【讨论】:

    【解决方案2】:

    我认为最好的解决方案是为您的过滤结果创建一个属性。

    public ICollection<People> FilteredPeople
        {
            get
            {
                return this._FilteredPeople;
            }
    
            set
            {
                if (value != null && !value.Equals(this._FilteredPeople))
                {
                    this._FilteredPeople = value;
                    this.OnPropertyChanged("FilteredPeople");
                }
            }
        }
    

    实现 INotifyPropertyChanged

        /// <summary>
        /// Triggered when a class property value is changed
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
    
        /// <summary>
        /// Helper for PropertyChanged event
        /// </summary>
        /// <param name="propertyName">Name of the property</param>
        protected void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    

    然后将事件处理程序添加到您的可观察集合 CollectionChanged 事件。在该处理程序中,将集合属性设置为过滤后的结果。绑定到 FilteredPeople 属性,然后离开。您可以轻松扩展它以参数化使用的名称。

    这将导致您的控件完全重绘,而不仅仅是添加元素,因此请注意,如果您的集合数量过多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-25
      • 2023-04-06
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 2021-08-31
      • 2014-04-06
      • 1970-01-01
      相关资源
      最近更新 更多