ObservableCollection in ViewModel is not updated when a List changes in Model

时光毁灭记忆、已成空白 提交于 2019-12-10 17:42:20

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!