17

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

一切都很好。

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

我假设绑定将继续查找属性的值,但它可能链接到一个被new破坏的引用。

我做对了吗?任何人都可以扩展这是如何联系起来的吗?当我的视图模型不知道视图时,有没有办法重新绑定它?

4

4 回答 4

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?");
    }
}
于 2013-02-09T01:06:11.093 回答
4

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

public ObservableCollection<int> Integers
{
    get { return this.integers; }
    set {
        if (this.integers != value)
        {
            this.integers = value;
            RaisePropertyChanged("Integers");
        }
    }
}
于 2013-02-09T01:06:23.577 回答
3

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

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

public void SomeMethod()
{
    MyList = new ObservableCollection<string>();
    RaisePropertyChanged("MyList");
}
于 2013-02-09T01:06:47.560 回答
2

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

两个简单的建议是INotifyPropertyChanged在包含 的类上实现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");
    }
}

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

public void HandleCollectionData(IEnumerable<string> incomingData)
{
    MyCollection.Clear();
    foreach(var item in incomingData)
    {
        MyCollection.Add(item);
    }
}
于 2013-02-09T01:11:47.167 回答