ObservableCollection未通知更新(MVVM WPF GridView)

本文关键字:WPF GridView MVVM 通知 更新 ObservableCollection | 更新日期: 2023-09-27 18:12:54

我有一个GridView问题,它由"People"填充

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最初会填充,但任何其他更改都不会对网格产生影响。我已经切换回直接查看Directory.People,并在添加人员时返回更新。

我已经检查过,当我把这个人添加到"dirctory.People"时,它确实表明列表中有一个新项目。

我能做些什么来迫使"People"变量认识到有变化,进而更新GridView吗?

提前感谢

Andy

ObservableCollection未通知更新(MVVM WPF GridView)

简单地说,目录对象上的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; } } 
}

现在,当一个新的人员添加到视图时,将自动更新。

现在我意识到这与上面略有不同,但如果是目录。人是ObservableCollection<T>,那么这应该起作用。

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

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属性即可离开。您可以很容易地将其扩展为参数化所使用的名称。

这将导致控件的完全重绘,而不仅仅是添加元素,因此,如果您的集合达到高计数,请注意这一点。