Reputation: 1996
Okay, I have an ItemsControl in a XAML file that binds to an ObservableCollection. The ObservableCollection is found on a view-model class (let's call this class ViewModelA), and each item in the ObservableCollection is an instance of another view-model class (let's call the class ViewModelB).
There is a property on ViewModelA, that, when changed, will indirectly change the values of properties found in many instances of the ViewModelB class. In other words, it doesn't go straight to ViewModelB and set its properties, thus causing an INotifyPropertyChange call, but rather goes down to the model, sets some property in my model, and that change in my model affects what ViewModelB should be showing the view.
How can I notify the view that something in ViewModelB has changed?
Upvotes: 4
Views: 4051
Reputation: 3367
Ideally, you'd be able to do like Reed Copsey indicated... Implement INotifyPropertyChanged on the model and have ViewModelB listen for those events. Then ViewModelB will pick up the changes no matter where the update happens.
However, In some cases the model doesn't (or can't) implement INotifyPropertyChanged. In this case, you may want to consider using an Event Aggregator pattern to pass a message between ViewModelA and the ViewModelB instances.
In this case, you could publish a "model changed" message from ViewModelA. The ViewModelB instances would subscribe to this message and each of them would get notified when A published the message. Then ViewModelB could raise the approriate PropertyChanged events to tell the UI what's changed.
You can find more info on Event Aggregator in many of the frameworks, including
Upvotes: 1
Reputation: 256
If change in Models will change in some properties of ViewModelB and those properties has change notification to UI (i.e. ViewModleB is implementing INotifyPropertyChanged), the change will immediately reflect in the UI.
So, if you have a ObservableCollection of another viewmodelB, you need not to hook up events for the propertychanged of that viewmodelB. According to my understanding, whoever changes viewmodelB's properties (model class or anyone else) and if the properties has change notification, the view will update automatically.
Upvotes: 0
Reputation: 11230
To solve this I created a class called VeryObservableCollection. For each object you add, it hooks the object's NotifyPropertyChanged event to a handler that triggers a CollectionChanged event. For each object removed, it removes the handler. Very simple and will give you exactly what you want. Partial code:
public class VeryObservableCollection<T> : ObservableCollection<T>
/// <summary>
/// Override for setting item
/// </summary>
/// <param name="index">Index</param>
/// <param name="item">Item</param>
protected override void SetItem(int index, T item)
{
try
{
INotifyPropertyChanged propOld = Items[index] as INotifyPropertyChanged;
if (propOld != null)
propOld.PropertyChanged -= new PropertyChangedEventHandler(Affecting_PropertyChanged);
}
catch (Exception ex)
{
Exception ex2 = ex.InnerException;
}
INotifyPropertyChanged propNew = item as INotifyPropertyChanged;
if (propNew != null)
propNew.PropertyChanged += new PropertyChangedEventHandler(Affecting_PropertyChanged);
base.SetItem(index, item);
}
Upvotes: 0
Reputation: 564931
You should be able to tell the View that the collection has changed, and in turn, trigger it to rebind to the entire collection (which would update the View).
If your Model implements INotifyPropertyChanged
, the other option would be to have your ViewModelB
class listen for changes on it's wrapped Model, and raise property changed events as needed.
Upvotes: 2