简体   繁体   English

ObservableCollection通知更新(MVVM WPF GridView)

[英]ObservableCollection not notifying update (MVVM WPF GridView)

I have an issue where I have a GridView, which is populated by "People" 我有一个GridView(由“人”填充)的问题

ObservableCollection<Person> People
{

    get { return directory.People }

    set { directory.People = value; } 
}

This is perfectly updating the GridView, but I want to instead only show people with the name "Andy", so I've changed it to be the following: 这是对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; } 

}

The above code will perfectly populate the GridView, but it will not update it if I do the following 上面的代码将完美地填充GridView,但是如果执行以下操作,它将不会更新它

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

What this means is that although the GridView will populate initially, any other changes will have no effect on the Grid. 这意味着,尽管最初将填充GridView,但是任何其他更改都不会对Grid产生影响。 I've switched back to looking directly at Directory.People, and it goes back to updating when people are added. 我转回到直接查看Directory.People,并在添加人员时返回到更新。

I've checked that when I add the person to "dirctory.People" it does say there is a new item in the list. 我已经检查过,当我将该人添加到“ dirctory.People”时,确实会说列表中有一个新项。

Is there something I can do to force the "People" variable to recognise that there are changes, an in turn for the GridView to update? 有什么我可以强迫“ People”变量识别出更改的方法,从而可以更新GridView吗?

Thanks a lot in advance, 提前多谢

Andy 安迪

Put simply there is no connection between the People property on the directory object and the ObservableCollection you are creating in the property accessor. 简而言之,目录对象上的People属性与您在属性访问器中创建的ObservableCollection之间没有任何连接。

So how does the XAML framework know when the directory.People collection has been updated? 那么XAML框架如何知道directory.People集合何时更新?

I would suggest using a ListCollectionView and expose this as the property on the ViewModel, 我建议使用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; } } 
}

Now when a new Person is added to View will automatically update. 现在,当将新的“个人”添加到“视图”时,它将自动更新。

Now I realize this is slightly different to the above, but if the directory.People is an ObservableCollection<T> then this should work. 现在我意识到这与上面的略有不同,但是如果directory.People是ObservableCollection<T>那么这应该可以工作。

I think the best solution is to create a property for your filtered results. 我认为最好的解决方案是为您的过滤结果创建一个属性。

public ICollection<People> FilteredPeople
    {
        get
        {
            return this._FilteredPeople;
        }

        set
        {
            if (value != null && !value.Equals(this._FilteredPeople))
            {
                this._FilteredPeople = value;
                this.OnPropertyChanged("FilteredPeople");
            }
        }
    }

Implement INotifyPropertyChanged 实现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));
        }
    }

Then add an event handler to your observable collections CollectionChanged event. 然后将事件处理程序添加到可观察的CollectionCollectionChanged事件中。 In that handler, set the collection property to your filtered results. 在该处理程序中,将collection属性设置为您的过滤结果。 Bind to the FilteredPeople property and away you go. 绑定到FilteredPeople属性,然后离开。 You can easily extend this to parametise the name used. 您可以轻松扩展此名称以使用所使用的名称。

This will cause a complete redraw of your control rather than just adding the elements so be aware of that if your collection runs in to high counts. 这将导致控件的完全重绘,而不仅仅是添加元素,因此请注意,如果您的集合运行过多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM