ObservableCollection没有通知更新(MVVM WPF GridView)

时间:2014-07-14 15:08:12

标签: c# wpf gridview mvvm observablecollection

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

ObservableCollection<Person> People
{

    get { return directory.People }

    set { directory.People = value; } 
}

这完全更新了GridView,但我只想向人们展示名称&#34; Andy&#34;,所以我将其更改为以下内容:

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,并且会在添加人员时重新更新。

当我将这个人添加到&#34; dirctory.People&#34;它确实说清单中有一个新项目。

我能做些什么来强迫'#34;人&#34;变量,以识别有变化,反过来GridView更新?

提前多多感谢,

安迪

2 个答案:

答案 0 :(得分:0)

简单地说,目录对象上的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时会自动更新。

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

答案 1 :(得分:0)

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

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财产,然后离开。您可以轻松扩展它以参数化使用的名称。

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