当Model中的List发生变化时,ViewModel中的ObservableCollection未被更新

3

假设我有一个模型类 Data,我想为它创建 DataViewModelDataView。数据类如下:

public class Data
{
    public Data()
    {
        RandomData = new List<String>();
    }

    public List<String> RandomData {get; set;}
}

我希望创建一个名为 DataViewModel 的类,它封装了属性 RandomData。我需要在某些 ListView 中绑定到该 RandomData 属性,并在底层模型的 RandomData 更改时更新它。

如果我这样做:

public class DataViewModel
{
    private Data _data;

    public DataViewModel(Data data)
    {
        _data = data;
        RandomData = new ObservableCollection<String>(_data.RandomData);
    }

    public ObservableCollection<String> RandomData {get; set;}
}

那么我就不会收到任何更新。 (我知道这只是复制列表,我只是用它来说明问题)。 如果我在RandomData属性上使用INotifyPropertyChanged,那么我只会收到分配给它的新列表的通知。 我如何检查内容的更改? 做这个的首选方式是什么?

感谢您提供任何建议。

3个回答

3

针对这个具体的例子,我会倾向于将你的模型更改为使用ObservableCollection。

public class Data
{
    public Data()
    {
        RandomData = new ObservableCollection<String>();
    }

    public ObservableCollection<String> RandomData {get; set;}
}

然后将其作为ReadOnlyObservableCollection在您的视图模型中公开。请注意,ReadOnlyObservableCollection是原始ObservableCollection的包装器。数据不会被复制,并且来自原始集合的更改通知会通过ReadOnlyObservableCollection反映出来。

public class DataViewModel
{
    public DataViewModel(Data data)
    {
        RandomData = new ReadOnlyObservableCollection<String>(data.RandomData);
    }

    public ReadOnlyObservableCollection<String> RandomData {get; private set;}
}

假设您希望视图模型RandomData是只读的。

是的,这很准确。看来我别无选择,只能使用ObservableCollections。 - Pavel Matuska

1
我认为,如果您想要注意现有集合中的更改,则需要使用INotifyCollectionChanged。

http://msdn.microsoft.com/en-us/library/system.collections.specialized.inotifycollectionchanged.aspx

实现这个接口可能是一个好的方法。然而,我相信在MVVM模型文章http://msdn.microsoft.com/en-us/magazine/dd419663.aspx中,Josh Smith在MSDN上甚至没有使用这个接口。我知道在他给出的示例中,他通过类似以下逻辑将客户添加到集合中:
void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
                foreach (CustomerViewModel custVM in e.NewItems)
                    custVM.PropertyChanged += this.OnCustomerViewModelPropertyChanged;

            if (e.OldItems != null && e.OldItems.Count != 0)
                foreach (CustomerViewModel custVM in e.OldItems)
                    custVM.PropertyChanged -= this.OnCustomerViewModelPropertyChanged;
        }

这是一个打字错误还是你的意思是我应该将Data的属性更改为ObservableCollection?因为我根本不能更改模型。更准确地说,我可以更改它,但难道没有其他方法吗? - Pavel Matuska
抱歉,我没有完全阅读你的问题。我认为你想要的接口是INotifyCollectionChanged,它会在集合添加和删除数据值时通知你,除了属性之外。http://msdn.microsoft.com/en-us/library/system.collections.specialized.inotifycollectionchanged.aspx - djangojazz
请查看我的更新答案,我把属性更改错认为集合更改了。在MSDN文章中,Josh Smith通过公开事件并计算它来直接处理逻辑。如果您下载示例,您可以看到客户端实时添加到主集合以及完全不同的视图。 - djangojazz
我接受了第二个答案,但两个都+1。感谢你的努力,使用ObservableCollection似乎是唯一的方法,不幸的是。 - Pavel Matuska

0

选项1(有点偏离MVVM但有效)。将此代码添加到您的View代码后台的OnNavigatedTo方法中,它将在任何时候刷新数据:

protected override void OnNavigatedTo(NavigationEventArgs e) {
this.DataContext = new YourViewModel();
}

选项2:

 raise RaisePropertyChanged(YourItem);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接