当我“新”它时,ObservableCollection失去绑定

时间:2013-02-09 00:56:30

标签: c# wpf binding

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

一切都很好。

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

我假设绑定会继续查找属性的值,但是它可能与 new 所销毁的引用相关联。

我做对了吗?任何人都可以扩展它的链接方式吗?当我的视图模型不了解视图时,有没有办法重新绑定它?

4 个答案:

答案 0 :(得分:14)

确保在重新集中集合后引发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?");
    }
}

答案 1 :(得分:4)

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

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

答案 2 :(得分:3)

假设您已在ViewModel上实现了INotifyPropertyChanged,则只要为其指定 new 值,就可以在ObservableCollection上引发属性更改事件。

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

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

答案 3 :(得分:2)

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

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

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

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

第二个,我通常更喜欢的选项是在收到新数据时清除并重新填充该集合。

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