2014-02-20 59 views
0

也许我不太了解ObservableCollection。但据我所知,它与正常列表类似,但具有事件触发器,因此您可以对变化做出反应。C#奇怪Double ObservableCollection行为

所以我有这个Windows商店应用程序。在这个应用程序中,我有一个主要的BusinessModel类,它是我的客户端应用程序中所有数据的主要来源。当服务器在其他地方做了一些更改时,这些数据将被更新。在未来,我想让这个类更新ViewModels的特定数据更新等。 所以我也有一个ViewModel类,至少在我的PoC中至少包含了该列表的一个副本(在不久的将来此列表将包含该列表的丰富版本)。 既然它是一个副本,它们应该是两个独立的实例,并有自己的单独项目。 但是,当我更新ViewModel中的副本时,BusinessModel版本随之更改。 反之亦然。

我似乎无法弄清楚为什么会发生这种情况。下面你会发现类及其功能:

//the BusinessModel Class 
public class ModelStuff : INotifyPropertyChanged 
{ 
    private ObservableCollection<DataObject> _modelStuff; 
    public ObservableCollection<DataObject> modelStuff 
    { 
     get 
     { 
      return _modelStuff; 
     } 
     set 
     { 
      _modelStuff = value; 
      NotifyPropertyChanged("modelStuff"); 
     } 
    } 

    private static ModelStuff businessModel; 

    public static ModelStuff BusinessModel 
    { 
     get 
     { 
      if (businessModel == null) 
      { 
       businessModel = new ModelStuff(); 
      } 
      return businessModel; 
     } 
    } 


    public ModelStuff() 
    { 
     modelStuff = new ObservableCollection<DataObject>(); 
     modelStuff.Add(new DataObject(0)); 
     modelStuff.Add(new DataObject(1)); 
     modelStuff.Add(new DataObject(2)); 
     modelStuff.Add(new DataObject(3)); 
     modelStuff.Add(new DataObject(4)); 
     modelStuff.Add(new DataObject(5)); 

    } 

    #region INotifyPropertyChanged 
    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
    #endregion 

} 

//the ViewModel class 
public class ViewModel : INotifyPropertyChanged 
{ 
    private ObservableCollection<DataObject> _visibleStuff; 
    public ObservableCollection<DataObject> visibleStuff 
    { 
     get 
     { 
      return _visibleStuff; 
     } 
     set 
     { 
      _visibleStuff = value; 
      NotifyPropertyChanged("visibleStuff"); 
     } 
    } 

    private static ViewModel tvm; 

    public static ViewModel TVM 
    { 
     get 
     { 
      if (tvm == null) 
      { 
       tvm = new ViewModel(); 
      } 
      return tvm; 
     } 
    } 
    public ViewModel() 
    { 
     visibleStuff = new ObservableCollection<DataObject>(ModelStuff.BusinessModel.modelStuff.OrderBy(c => c.testNumber)); 
    } 

    #region INotifyPropertyChanged 
    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
    #endregion 
} 

//the TestObjects 
public class DataObject 
{ 
    public int testNumber { get; set; } 
    public String testStr { get; set; } 

    public DataObject(int i) 
    { 
     testNumber = i; 
     testStr = "testje"; 
    } 

} 

//A randomly placed button invokes this function when clicked. 
private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    //do stuff here 
    int i0 = ModelStuff.BusinessModel.modelStuff[0].testNumber; 
    ViewModel.TVM.visibleStuff[0].testNumber = 100; 
    int i1 = ModelStuff.BusinessModel.modelStuff[0].testNumber; 
    //i1 has the value 100 in my logs! :S 
} 

//Second version but vice versa 
private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    //do stuff here 
    int i0 = ViewModel.TVM.visibleStuff[0].testNumber; 
    ModelStuff.BusinessModel.modelStuff[0].testNumber = 100; 
    int i1 = ViewModel.TVM.visibleStuff[0].testNumber; 
    //i1 has the value 100 in my logs! :S 
} 

哪里有我的推理哪里呢? 这是怎么回事? 更重要的是,我该如何防止这种行为?

回答

2

据我所看到的,你的代码行:

visibleStuff = new ObservableCollection<DataObject>(ModelStuff.BusinessModel.modelStuff.OrderBy(c => c.testNumber)); 

没有对底层对象的拷贝都没有。它将原始列表中的相同DataObjects添加到新的ObservableCollection中。

您需要单独克隆DataObjects并将它们添加到新集合中。像这样的东西应该这样做:

visibleStuff = new ObservableCollection<DataObject>(ModelStuff.BusinessModel.modelStuff.OrderBy(c => c.testNumber).Select(i => new DataObject(i.testNumber))); 
+0

这是否意味着它将一组指针复制到新集合?当我阅读msdn文档(http://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx)时,实际上是这样说的:“初始化包含元素的ObservableCollection 类的新实例从指定集合复制(!!)“。 –

+0

元素*被复制。元素是参考! :) – Baldrick

+0

为了扩展我的最后一条评论,没有(有注意事项!)执行对象的深层复制的一般方法。你必须自己编写代码(在类中),并且当你需要一个新的对象,它是一个现有对象的深层副本时调用它。 – Baldrick