【问题标题】:ObservableCollection in ViewModel is not updated when a List changes in Model当模型中的列表更改时,ViewModel 中的 ObservableCollection 不会更新
【发布时间】:2013-03-09 23:22:15
【问题描述】:

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

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

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

我想创建封装RandomData 属性的DataViewModel。我需要在一些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,那么我只会收到分配给它的新列表的通知。我如何检查内容的更改?这样做的首选方法是什么?

感谢您的任何建议

【问题讨论】:

    标签: c# wpf mvvm mvvm-light observablecollection


    【解决方案1】:

    对于这个特定示例,我很想将您的模型更改为使用 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。
    【解决方案2】:

    我相信会注意到您想要使用 INotifyCollectionChanged 的​​现有集合中的更改。

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

    实现这个接口可能是一个很好的使用方法。但是,我相信 MSDN 中的 MVVM 模型文章 http://msdn.microsoft.com/en-us/magazine/dd419663.aspx 中,Josh Smith 甚至不使用此接口就可以做到这一点。我知道在他给出的示例中,他将客户添加到具有类似逻辑的集合中:

    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?因为我根本无法更改模型。更准确地说,我可以更改它,但没有其他方法吗?
    • 抱歉,我没有完全阅读您的问题。我相信您想要的接口是 INotifyCollectionChanged,除了属性之外,它还会让您知道集合何时向其中添加和删除数据值。 msdn.microsoft.com/en-us/library/…
    • 查看我的更新答案,我将属性更改误认为是集合更改。我在 MSDN 文章中知道 Josh Smith 通过公开事件并对其进行说明来直接处理逻辑。我知道,如果您下载该示例,您可以看到客户实时添加到您的主要收藏中,并以完全不同的视图显示。
    • 我接受了第二个答案,但两者都 +1。感谢您的努力,不幸的是,使用 ObservableCollection 似乎是唯一的方法。
    【解决方案3】:

    选项 1(与 MVVM 稍有区别但有效)。将此添加到您的 View 代码隐藏的 OnNagivatedTo 中,它将随时刷新数据:

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

    选项 2:

     raise RaisePropertyChanged(YourItem);
    

    【讨论】:

      猜你喜欢
      • 2018-05-18
      • 1970-01-01
      • 2013-09-22
      • 2011-11-15
      • 2018-03-31
      • 2014-11-02
      • 2021-11-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多