AdvancedPropertyChanged event

Topics: Feature requests, Issues / bugs
Sep 10, 2013 at 10:20 PM
I have a typical property registration with a method to be called "on property changed". My issue with it is that it isn't really a property changed event but rather property changing event: I can see the old and new value in the arg but if I update fields that depend on it they would use the old value. It's ok if I use the OnModelPropertyChanged event instead but that forces me to use a switch and I would much rather have a MyPropertyChangedEvent. Naturally having both changed and changing events would be even better.
Coordinator
Sep 11, 2013 at 4:27 PM
Catel also supports the INotifyPropertyChanging event. You can subscirbe to these properties as long as the models you use implement this interface.
Sep 11, 2013 at 4:43 PM
Ok I guess I'm not explaining/understanding this correctly:
As I see it in my VM I have those options:
  1. override OnPropertyChanged(AdvancedPropertyChangedEventArgs e)
  2. ** OnModelPropertyChanged **
  3. register my prop like this: RegisterProperty("Count", typeof (int), -1, (sender, args) => ((ProducedBottleTypeViewModel)sender).CountChanged(args));
    Correct me if I'm wrong but the last one isn't really a a property changed but rather property changing event.
    How do make the last one into a property changed event?
Coordinator
Sep 13, 2013 at 9:40 AM
Edited Sep 13, 2013 at 9:41 AM
Why do you think that?

1) This line shows that the value is set before calling RaisePropertyChanged
2) This line shows that the handler registered to the property data is invoked in RaisePropertyChanged
Sep 13, 2013 at 3:46 PM
Indeed the Count property in the VM is changed in option 3 but the change hasn't yet been reflected to the model:
CountChanged: Count = 5 args.newvalue = 5 Model.Count = 4
Model Property Changed: Model.Count= 5
Coordinator
Sep 13, 2013 at 3:48 PM
Can you provide a repro? The only thing I can think of is that the Count is changed inside a handler, which is called later than the actual registered PropertyChangedlHandler of the propertydata itself.
Sep 13, 2013 at 4:38 PM
I did a trace:
// value is changed in the view (numeric up-down btn)
Step into: Stepping over non-user code 'Catel.Data.ModelBase.SetValue'
Step into: Stepping over non-user code 'Catel.Reflection.PropertyHelper.TryGetPropertyValue<object>'
Step into: Stepping over non-user code 'Catel.Reflection.PropertyHelper.TryGetPropertyValue'
Step into: Stepping over non-user code 'Catel.MVVM.Auditing.AuditingHelper.OnViewModelPropertyChanging'
Step into: Stepping over non-user code 'Catel.Data.ObservableObject.RaisePropertyChanging'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.SetValue'
CountChanged: Count = 7 args.newvalue = 7 Model.Count = 6
// the model properties are validated, with Count==6
Step into: Stepping over non-user code 'Catel.Data.ModelBase.RaisePropertyChanged'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.GetValue<int>'
Step into: Stepping over non-user code 'Catel.Reflection.PropertyHelper.TryGetPropertyValue<object>'
Step into: Stepping over non-user code 'Catel.Reflection.PropertyHelper.TryGetPropertyValue'
Step into: Stepping over non-user code 'Catel.MVVM.Auditing.AuditingHelper.OnViewModelPropertyChanged'
Step into: Stepping over non-user code 'Catel.MVVM.ViewModelCommandManager.OnViewModelPropertyChanged'
Step into: Stepping over non-user code 'Catel.MVVM.ManagedViewModel.OnViewModelPropertyChanged'
Step into: Stepping over non-user code 'Catel.Windows.Controls.MVVMProviders.Logic.LogicBase.OnViewModelPropertyChanged'
Step into: Stepping over non-user code 'Catel.MVVM.ViewModelBase.OnChildViewModelPropertyChanged'
Step into: Stepping over non-user code 'System.ComponentModel.PropertyChangedEventManager.OnPropertyChanged'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.GetValue<int>'
Step into: Stepping over non-user code 'Catel.MVVM.ViewModelPropertyDescriptor.GetValue'
Step into: Stepping over non-user code 'MS.Internal.Data.PropertyPathWorker.GetValue'
Step into: Stepping over non-user code 'MS.Internal.Data.PropertyPathWorker.RawValue'
Step into: Stepping over non-user code 'MS.Internal.Data.PropertyPathWorker.RawValue'
Step into: Stepping over non-user code 'MS.Internal.Data.ClrBindingWorker.RawValue'
Step into: Stepping over non-user code 'System.Windows.Data.BindingExpression.TransferValue'
Step into: Stepping over non-user code 'Catel.MVVM.ViewModelBase.OnValidatingFields'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.Validate'
Step into: Stepping over non-user code 'Catel.MVVM.ViewModelBase.OnValidatingBusinessRules'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.Validate'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.Validate'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.FieldErrorCount.get'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.HasErrors.get'
Step into: Stepping over non-user code 'System.Windows.Data.BindingExpression.GetDataErrors'
Step into: Stepping over non-user code 'System.Windows.Data.BindingExpression.UpdateNotifyDataErrors'
Step into: Stepping over non-user code 'System.Windows.Data.BindingExpression.TransferValue'
Step into: Stepping over non-user code 'MS.Internal.Data.ClrBindingWorker.NewValueAvailable'
Step into: Stepping over non-user code 'MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState'
Step into: Stepping over non-user code 'System.Windows.WeakEventManager.ListenerList<System.ComponentModel.PropertyChangedEventArgs>.DeliverEvent'
Step into: Stepping over non-user code 'System.ComponentModel.PropertyChangedEventManager.OnPropertyChanged'
Step into: Stepping over non-user code 'Catel.MVVM.Views.ViewToViewModelMappingHelper.OnViewModelPropertyChanged'
Step into: Stepping over non-user code 'Catel.EventHandlerExtensions.SafeInvoke'
Step into: Stepping over non-user code 'Catel.Data.ObservableObject.RaisePropertyChanged'
// finally inside the model setter: value '7' is set and model is re-validated
Step into: Stepping over non-user code 'Catel.MVVM.ViewModelBase.OnValidatingFields'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.Validate'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.Validate'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.SetDirtyAndAutomaticallyValidate'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.RaisePropertyChanged'
Step into: Stepping over non-user code 'Catel.Data.ModelBase.OnPropertyObjectPropertyChanged'
Step into: Stepping over non-user code 'Catel.EventHandlerExtensions.SafeInvoke'
Step into: Stepping over non-user code 'Catel.Data.ChangeNotificationWrapper.OnObjectPropertyChanged'
Step into: Stepping over non-user code 'Catel.WeakEventListener<Catel.Data.ChangeNotificationWrapper,Sklad.Data.ProducedBottle,System.ComponentModel.PropertyChangedEventArgs>.OnEvent'
Step into: Stepping over non-user code 'Catel.MVVM.ViewModelBase.OnModelPropertyChangedInternal'
Model Property Changed: Model.Count: 7
Coordinator
Sep 13, 2013 at 5:14 PM
Ah, it's a combination of a model and a view model. Is it possible to create a very small repro of this? Then I can easily help you out.