wpf ObservableCollection 在我“新建”它时失去绑定

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14783750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 07:26:32  来源:igfitidea点击:

ObservableCollection loses binding when I "new" it

c#wpfbinding

提问by TomDestry

I have a ListBox on my UI that is bound to a property of ObservableCollection. I set a new instance of the ObservableCollection into the property in the view model's constructor and I can add items to it with a button on the form. These are visible in the list.

我的 UI 上有一个 ListBox,它绑定到 ObservableCollection 的一个属性。我在视图模型的构造函数中将 ObservableCollection 的一个新实例设置到属性中,我可以使用表单上的按钮向其中添加项目。这些在列表中可见。

All is good.

一切都很好。

However, if I reinitialize the property with newin the button callback, it breaks the binding and the UI no longer shows what is in the collection.

但是,如果我在按钮回调中使用new重新初始化属性,则会破坏绑定并且 UI 不再显示集合中的内容。

I assumed the binding would continue to look up the values of the property, but its presumably linked to a reference which is destroyed by the new.

我假设绑定会继续查找属性的值,但它可能链接到被new销毁的引用。

Have I got this right? Can anyone expand on how this is linked up? Is there a way to rebind it when my view model has no knowledge of the view?

我做对了吗?谁能详细说明这是如何联系起来的?当我的视图模型不知道视图时,有没有办法重新绑定它?

采纳答案by Ryan Byrne

Make sure you are raising a PropertyChangedEvent after you reintialize your collection. Raising this event will allow the view to handle changes to the property with the model having no knowledge of the view.

确保在重新初始化集合后引发 PropertyChangedEvent。引发此事件将允许视图在模型不了解视图的情况下处理对属性的更改。

class Model : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }

    private ObservableCollection<string> _list = new ObservableCollection<string>();
    public ObservableCollection<string> List
    {
        get { return _list; }
        set 
        { 
            _list = value;
            NotifyPropertyChanged("List");
        }
    }

    public Model()
    {
        List.Add("why");
        List.Add("not");
        List.Add("these?");
    }
}

回答by RayB64

I think based on your description that what you need to do is refactor the property that exposes your ObservableCollection so that it raises a PropertyChanged event also when it is assigned a new value. Example:

我认为根据您的描述,您需要做的是重构公开 ObservableCollection 的属性,以便在为其分配新值时也引发 PropertyChanged 事件。例子:

public ObservableCollection<int> Integers
{
    get { return this.integers; }
    set {
        if (this.integers != value)
        {
            this.integers = value;
            RaisePropertyChanged("Integers");
        }
    }
}

回答by Joao

Supposing you've implemented INotifyPropertyChanged on your ViewModel, you can raise the property changed event on your ObservableCollection whenever you assign a newvalue to it.

假设您已经在 ViewModel 上实现了 INotifyPropertyChanged,您可以在为 ObservableCollection 分配值时引发属性更改事件。

public ObservableCollection<string> MyList { get; set; }

public void SomeMethod()
{
    MyList = new ObservableCollection<string>();
    RaisePropertyChanged("MyList");
}

回答by Peter Karlsson

Updates to the ObservableCollectionare handled by hooking in to the CollectionChangedevent so when you create a new ObservableCollectionyour observer is still looking at the old collection.

对 的更新ObservableCollection是通过挂钩CollectionChanged事件来处理的,因此当您创建一个新ObservableCollection的观察者时,您仍然在查看旧的集合。

Two simple suggestions would be either to implement INotifyPropertyChangedon the class that contains the ObservableCollectionand raising the PropertyChangedevent in the setter of the collection property (don't forget to unhook from the old one first in your observer if it's your own code).

两个简单的建议要么是INotifyPropertyChanged在包含集合属性的 setter的类上实现,要么在集合属性的 setter 中ObservableCollection引发PropertyChanged事件(如果它是您自己的代码,请不要忘记首先在您的观察者中取消旧的)。

private ObservableCollection<string> _myCollection = new ObservableCollection<string>();
public ObservableCollection<string> MyCollection
{
    get { return _myCollection; }
    set
    {
        if(_myCollection == value)
            return;

        _myCollection = value;
        RaisePropertyChanged("MyCollection");
    }
}

A second, and the option I generally prefer is to just clear and repopulate the collection with your new data when it arrives.

其次,我通常更喜欢的选项是在新数据到达时清除并重新填充集合。

public void HandleCollectionData(IEnumerable<string> incomingData)
{
    MyCollection.Clear();
    foreach(var item in incomingData)
    {
        MyCollection.Add(item);
    }
}