Does DataObjectBase fire PropertyChanged?

Apr 13, 2012 at 2:17 PM

Hi Geert,

firstly, let me reproduce my scenario.

I have model class inheriting the DataObjectBase. This model contains only few properties of type boolean defined as catel properties using dataprop snippet. In my ViewModel (inheriting ViewModelBase), i use the model in common way - vmpropmodel. As I need several instances of my model, I am not able to expose properties using standard ViewModelToModelMapping, so I have to access the properties of model using way in ma view.

The problem is that the model doesn't seem to fire PropertyChanged event when I change one of its properties form the view. Yes, it becomes dirty, but in the viewmodel, there is no way to determine that the model has actually changed. Is this behaviour correct or am I missing something? Do you have some idea how could I force my model to fire the event when one of its properties changes?

If my explanation isn't clear enough, I will try to make some repro of this situation.

Thank you in adavance.


P.S. Using Catel 3.0 under .NET 4 in WPF app.

Apr 13, 2012 at 2:35 PM

The model *should* throw property change notifications. If you subscribe manually to your model (model.PropertyChanged += (s, e) => Console.WriteLine(e.PropertyName)), does it get there?

If the Model.IsDirty gets true, it definitely raises the PropertyChanged event. You can always fire the event manually, but this is not the issue. First, check if the code above writes the properties to the console. Then we can pinpoint the issue.

Apr 17, 2012 at 9:22 AM

Thank you, subscribing to the event this way in VM constructor works. But trying to subscribe in model property definition like:

 public ModelType MyModel
 get { return GetValue<ModelType>(MyModelProperty); }
 set { SetValue(MyModelProperty, value); }

 public static readonly PropertyData MyModelProperty = RegisterProperty("MyModel", typeof(ModelType), null,
 (sender, e) => ((MyViewModel)sender).DoSomething(e));

never catches the change event.

Apr 17, 2012 at 9:35 AM

Keep in mind that you have two separate property definitions. The first example I gave raises a property changed event for every change on the model object itself. The second example that you posted will only raise a property changed when the model is replaced by another instance. Thus, depending on what you need, make sure to make the right call.

Apr 17, 2012 at 10:02 AM

Yes, thanks, this is exactly what I was asking for.


Apr 17, 2012 at 10:08 AM

So actually, you are looking for some kind of OnModelPropertyChanged method on the view model? That should be easy to fix.

Apr 17, 2012 at 11:00 AM

No, the solution:

model.PropertyChanged += (s, e) => Console.WriteLine(e.PropertyName)

is ok and works fine for me. I was wonering why changing the property of model didn't fire the ModelChangedEvent as I thought that these events are routed from properties together with setting IsDirty property. After your explanation I understand that the Model isn't expected to do this.

In most cases this is not an issue as usually there is not more than one Model of one type in one viewmodel and you can map the properties with ViewModelToModel and access them directly obtaining all the benefits provided.

Apr 17, 2012 at 11:06 AM

Great! Just keep in mind that you also need to re-subscribe on every model change and unsubscribe as well to prevent memory leaks. However, I also added the OnModelPropertyChanged so you can use whatever you like (but the method takes care of the memory leak prevention for you).

Apr 17, 2012 at 11:23 AM

Not sure if i understand this. Resubscribing is not problem for me as I am tot able to change the model. But what about unsubscription? My model (with the viewmodel together) dies with no control - it is the datacontext of nested view in master-detail scenario. Am I correct as I write that the PropertzChanged event handler dies together with viewmodel thus no unsubscription is necessary? MAybe a dumb question but you made me doubt.

Apr 17, 2012 at 11:55 AM

If the model really dies (gets our of scope), then it is ok, but I don't think the model dies. The model will have a reference to the method to call when a property changed, which keeps the VM alive (in memory). Therefore, you have your very first (probably not the first ;)) memory leak introduced.

You can read all about it in this blog post. You can solve this by using the WeakEvenLtistener in Catel.