问题
Let's say I have a model class Data
and I would like to create DataViewModel
and DataView
for it. The data class looks like this:
public class Data
{
public Data()
{
RandomData = new List<String>();
}
public List<String> RandomData {get; set;}
}
I want to create DataViewModel
that encapsulates RandomData
property. I need to bind to that RandomData
property in some ListView
and have it updated when the underlying model's RandomData
changes.
If I do this:
public class DataViewModel
{
private Data _data;
public DataViewModel(Data data)
{
_data = data;
RandomData = new ObservableCollection<String>(_data.RandomData);
}
public ObservableCollection<String> RandomData {get; set;}
}
then I don't receive any updates. (I am aware that is just copying the list, I just use it to get the point across). If I used INotifyPropertyChanged on the RandomData
property then I'd only receive notifications of new Lists being assigned to it. How do I check for change to the contents instead? What is the preferred way of doing this?
Thank you for any suggestions
回答1:
For this specific example I would be tempted to change your model to use an ObservableCollection
public class Data
{
public Data()
{
RandomData = new ObservableCollection<String>();
}
public ObservableCollection<String> RandomData {get; set;}
}
and then expose this in your view model as a ReadOnlyObservableCollection. Note that ReadOnlyObservableCollection is a wrapper over the original ObservableCollection. The data isn't copied and change notifications from the original collection are reflected by the ReadOnlyObservableCollection.
public class DataViewModel
{
public DataViewModel(Data data)
{
RandomData = new ReadOnlyObservableCollection<String>(data.RandomData);
}
public ReadOnlyObservableCollection<String> RandomData {get; private set;}
}
This is assuming that you want the view model RandomData to be read-only of course.
回答2:
I believe to take notice of changes in an existing collection you would want to use INotifyCollectionChanged.
http://msdn.microsoft.com/en-us/library/system.collections.specialized.inotifycollectionchanged.aspx
Implementing this interface may be a good method to use. However I believe in the MVVM model article, http://msdn.microsoft.com/en-us/magazine/dd419663.aspx, in MSDN Josh Smith does this without even using this interface. I know in the example he gives he adds customers to a collection with logic similar to:
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;
}
回答3:
Option 1 (a little bit aside of MVVM but works). Add this to OnNagivatedTo of your View code-behind and it will refresh the data anytime:
protected override void OnNavigatedTo(NavigationEventArgs e) {
this.DataContext = new YourViewModel();
}
Option 2:
raise RaisePropertyChanged(YourItem);
来源:https://stackoverflow.com/questions/15530770/observablecollection-in-viewmodel-is-not-updated-when-a-list-changes-in-model