4

I have my MVVM and the model consists of a number of related classes, but for the sake of this question we'll focus on just four.

GrandParentModel, ParentModel, ChildModel and Contact.

These all inherit from ModelBase which has an implementation of INotifyPropertyChanged on it.

So each of the three models has a Contact property. If Child doesn't have a property it is supposed to look to Parent, and if Parent is blank it will look to GrandParent. If the contact changes at the grandparent level I'd like any dependants, ie any sub parents and their children to raise a PropertyChanged event for their Contact too.

I think everything I'm going to do will be supported by the DependencyProperty system, but I don't want to use that as this is my Model, separation of concerns and all that. So I'm putting together a mini implementation, which is all fine.

My question is has anyone been down this path before and is there anything I should be worried about in the future? My Spidey-Senses are tingling and I don't know why.

Thanks Ian

Edit: The relationship between the objects here is that a grandparent has any number of parents has any number of children. My current model has a property on each which points at the parent (null in the case of a grandparent) and a parent/grandparent has a collection of child objects.

Ian
  • 4,885
  • 4
  • 43
  • 65
  • Could you please add an example of the class hierarchy/relationships? (preferably with pseudocode) Are they "is a" or "has a" relationships? Complex properties or Collections? etc. – Aaron Hoffman Jan 12 '11 at 16:29
  • IN this case my ModelBase contains a parent property which is set to the object's parent on creation, I will post a full solution if I can get the code length down to something that will fit here. I've added a little edit above, the structure isn't fixed in stone to be honest. – Ian Jan 13 '11 at 13:28

1 Answers1

3

I've been down this path, and it's not pretty. Basically you have to subscribe to the PropertyChanged event of ParentModel from your ChildModel. You have to take care if your child can change parents. Then when you get notified of a change in the parent from the child's point of view, you have to raise your own PropertyChanged event on the child. It gets ugly because you can end up with hanging event handlers that you forgot to clean up.

A better method would be to create your own Model-specific analog to DependencyProperty. Basically in your constructor of ChildModel you "declare" that property Contact delegates to property Contact of object Parent when null. You do that using a little helper class that observes the PropertyChanged event on the ParentModel object and have it execute a PropertyChanged event on the child when appropriate. Also have it watch for the Parent property to change on the child.

You could use the MVVM Light message bus. Have the grandparent and parent all send a message when their Contact property changes. Have the child listen for those messages. When it gets a message, then check to see if it matches its own parent or grandparent, and raise a PropertyChanged event if necessary. This is better than either method above because you don't have to keep track of when your parent or grandparent changes. You're less likely to have bugs. It also uses weak references, so it won't hold on to objects the way event handlers do.

Now what I've been doing is getting away from having my model objects implement INotifyPropertyChanged. I introduced a Presenter layer between my Model and my ViewModel. The Presenter actually constructs a ViewModel out of small ViewModel "widgets" (one widget might be a ChangeValue<T> widget, for instance). I have a rules engine that tells the Presenter how to compose a ViewModel out of widgets for a given Model. The Presenter handles all user input (basically executing a lambda against the Model), but since it knows that a user action just took place, it knows that something in the Model might have changed. After the Model action is complete, it copies all of the data from the Model to the ViewModel. The ViewModel inspects the incoming data and raises a PropertyChanged event if the field actually changed. Obviously that's the most compliated way of doing it, but it gives you a really clean Model and neither the ViewModel nor the Presenter contains any Model (domain/business) logic.

Scott Whitlock
  • 13,739
  • 7
  • 65
  • 114
  • Interesting. I did put together a Dependency property like class, I'll post a cut down version tomorrow when I'm back in front of the code. I like your Presenter concept, I've started doing something a little similar I think, so it's good to hear what you're saying, it will help me I think :) – Ian Jan 12 '11 at 22:15
  • Okie dokie I've got a solution, but I think it will be too long to post here. I'll put a blog post together and post the url for that if that's allowed. – Ian Jan 13 '11 at 14:32
  • @Ian - I'd like to see that actually. Please post it. – Scott Whitlock Jan 13 '11 at 15:21
  • Here you go: http://wp.me/p1haNJ-6 Please keep in mind it's my first draft, so it's a bit scrappy, but at the same time, do tear it apart and comment freely, I'm always happy to learn. Let me know if there are any issues on the blogging side, It's my first blog post ever bizarrely :) – Ian Jan 13 '11 at 22:15
  • Right, I've also figured out that WordPress can do code formatting too, so when I get home I'll update the post :) – Ian Jan 14 '11 at 15:14
  • @Ian - I like it as a start, but the magic strings are a bit scary. Obviously for starters you could just declare them as constants at the highest level. However, you can also use some reflection to get the property name at load time into a static variable. See the GetPropertyName method in [this file](http://svn.soapboxcore.com/svn/trunk/SoapBox/SoapBox.Utilities/NotifyPropertyChangedHelper.cs). – Scott Whitlock Jan 18 '11 at 16:27