I'm guessing that the ObservableObject
class is your own implementation of INotifyPropertyChanged
interface. Now to solve your issues:
You should register to
CollectionChanged
event in_punchDetailModels
and raise aPropertyChanged
event for that variable in the handler, like so:public ObservableCollection<PunchDetailModel> PunchDetailModels { get { return _punchDetailModels; } set { Set(PunchDetailModelsPropertyName, ref _punchDetailModels, value); _punchDetailModels.CollectionChanged += handler; } } private void handler(object sender, NotifyCollectionChangedEventArgs e) { base.RaisePropertyChanged(PunchDetailModelsPropertyName); // If you don't have a method with such signature in ObservableObject (one that takes a string and raises PropertyChanged for it) you'll have to write it. }
This way the view should reload automatically when adding or removing elements from the inner collection.
There is no other way than to subscribe to listen to
PropertyChanged
on these fields. That's what theView
does and that's what theViewModel
should do also. Like so:public const string AttendanceCollectionPropertyName = "AttendanceCollection"; private ObservableCollection<AttendanceModel> _attendanceCollection = null; public ObservableCollection<AttendanceModel> AttendanceCollection { get { if (_attendanceCollection == null) { _attendanceCollection = new ObservableCollection<AttendanceModel>(); } return _attendanceCollection; } set { Set(AttendanceCollectionPropertyName, ref _attendanceCollection, value); _attendanceCollection.CollectionChanged+= handler } } private void handler(object sender, NotifyCollectionChangedEventArgs e) { foreach (AttendanceModel model in AttendanceCollection) model.PropertyChanged += somethingChanged; } // Very ineffective to subscribe to all elements every time a list changes but I leave optimization to you. private somethingChanged (object obj, PropertyChangedEventArgs args) { if ( args.PropertyName == "CheckIn" ) // for example { AttendanceModel ModelToRecalculate = obj as AttendanceModel; // You can do anything you want on that model. } }
And of course you need to raise PropertyChanged
with string
argument of value CheckIn
in the AttendanceModel
class when You think it's necessary ( for example in the handler
method)
EDIT:
To answer your comment question:
"Come to second one - I need to recalculate the Attendance Model properties like InOutCount, TotalInTime, TotalOutTime on PunchTime field update."
The answer is: You don't need to do anything in the ViewModel
to "recalculate". The UI is subscribed to PropertyChange
for InOutCount
, FirstCheckIn
... and so on. It's beacause of Binding
(it does it automatically).
So All you need to do to inform the UI that given model needs to be recalculated is call RaisePropertyChanged("InOutCount")
, RaisePropertyChanged("FirstCheckIn")
.
The UI will understand that it needs to GET these properties and because you have these calcualations in property getters, it'll get recalculated.
So, I see that UI needs to be recalculated every time that the INNER list changes, so all you need to do is change the handler
code to CollectionChanged
for PunchDetailModels
like this:
// the handler for CollectionChanged for the INNER collection (PunchDetailModels)
private void handler(object sender, NotifyCollectionChangedEventArgs e)
{
base.RaisePropertyChanged(PunchDetailModelsPropertyName); // If you don't have a method with such signature in ObservableObject (one that takes a string and raises PropertyChanged for it) you'll have to write it.
base.RaisePropertyChanged("InOutCount")
base.RaisePropertyChanged("FirstCheckIn")
base.RaisePropertyChanged("LastCheckOut")
// and so on for all the properties that need to be refreshed
}