DependencyProperty analogue for WPF MVVM Model - mvvm

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.

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.

Related

Knockout Model vs ViewModel

I am trying to understand the difference between Model and ViewModel in KO. I understand the conceptual difference, but to me it seems that all Models in KO will become or are candidates to become ViewModels. Ill explain:
Say you have a table with a row of seats, so in your main ViewModel you will initialise and load a collection of objects from a Seat Model into an observable array.
Now you want to hide display seats based on a certain property of seats...this is the point where your model becomes another viewmodel...
So is it right to say that in KO all we have is ViewModels?
Yes. Essentially, anything with a ko.observable is creating a ViewModel. You could create a simple javascript model expressible as nothing but JSON, and wrap it, but the "model" in Knockout's MVVM pattern generally exists only on the server. You get the model data from the server, and you send model data back to the server (remember, you don't send the observables, just their data)
Knockout doesn't really care about where the model comes from, because its primary role is to deal with the databinding between the declarative view (HTML) and the ViewModel (with its View-aware observables).
The MVVM pattern is completed by technology outside of Knockout, since it's a client-side only framework. You could say that it is just the VVM part of the pattern, but that is confusing.

WCF RIA Services / intercept or subscribe to a RaiseDataMemberChanging

So I'm new to the concept of routed events, but I know that messages are flying everywhere when fields are changing via the RaiseDataMemberChanging / RaiseDataMemberChanged messages.
The quick question is how to I "listen" for those routed messages?
I would like my view model, in a MVVM correct matter, intercept a message that a field is being updated, deep down in the heirarchy of tables. If a change occurs in a child (a date range), that date range change has some business logic associated with it that works from top down.
I've know that I can use partial methods to inject code during the changing and changed events, but the design (one to one relationship) means that a change to the child, in the context of the child, has no reference the parent (Parent has a one to one reference to child, but child has no reference to parent).
Yes I can add the reference from the child to the parent (making the parent have both a one to one, as well as a one to many relationship), but during creation of the entity, this creates a problem - parent has to exist before the child entity exists, and the child entity has to exist before a reference to the parent can exist. This design requires an insert of the parent, and child, then an update of the child - which confuses WCF RIA Services during the inital creation process.
Sorry for the long winded explaination, but I'll even consider design changes if this all makes sense to anyone that cares to comment.
Any input would be appreciated.
I'm using a subscription to the PropertyChanged events of the Entity in question. It seems like a lot of work to filter out all the events for a couple of fields.
Using RX, I'm hoping that the resources used are minimal, and the weak reference avoids the memory link issue when a strong reference is used to deal with events:
Observable.FromEventPattern<PropertyChangedEventArgs>(this.FlowEntity, "PropertyChanged")
.Where(pPropertyChanged => (
pPropertyChanged.EventArgs.PropertyName.EndsWith("Date")) ||
pPropertyChanged.EventArgs.PropertyName == "Capacity"
)
.Subscribe(pObserver => this.RaiseFlowEntityDateChanged(this, pObserver.EventArgs));
FlowEntity is the child entity that I'm monitoring from the parent. I then raise custom event using the parent entity, rather than the entity that actually holds the event.
I can't raise this event from the partial methods, as the child entity would not have the context of the parent.

WP7: can i use IEnumerable in ViewModel instead of ObservableCollection?

I'm rather new to WP7 dev and I'm trying to play with data binding. I have an XML file and I want to represent it in a ListBox. I've made a ModelView on which I make a Linq query, the result of which I want to put in a ListBox. I've seen that many examples of DataBinding use the ObservableCollection class. I would like to use Linq to get the results instead of looping row by row, but if I use the IEnumerable instead of ObservableCollection, DataBinding does not work. Is that normal?
Silverlight works on a property changed mechanism to be notified when a property has changed in order to update a data binding. You can either use dependency properties (highly unlikely for a view model) or implement the INotifyPropertyChanged interface in your view model class.
In the case of ObservableCollection, it actually raises the CollectionChanged event when it's contents change (add/remove/insert), which also prompts the data binding to update. In your case, by binding to an IEnumerable, the data binding mechanism doesn't know when the contents has changed because there are no events raised.
If every action results in a new list, then you're not gaining anything by creating an ObservableCollection each time you re-query. So you'll need to implement the INotifyPropertyChanged interface and raise property change notification for yrou IEnumerable property when you re-query.
If you have items to add/remove each time you re-query, then creating an ObservableCollection the first time and then calling Add/Remove on each query will work just fine.
I guess it has to be an IList to work. IEnumerable won't work.
Try adding .ToList() to your LINQ query to convert it to List<T>.
As for ObservableCollection<T>, you need to use it if you plan to change items in that collection so that the UI automatically refreshes itself.
You can create an ObservableCollection from an enumerable by passing it to one of the constructors for the OC.
ObservableCollection<Foo> x = new ObservableCollection<Foo>(enumerable);
Courtesy of Cast LINQ result to ObservableCollection
Of course, this only applies if you want to avoid looping through the records yourself and don't have a reason due to behaviour in the code.
but if I use the IEnumerable instead of ObservableCollection, DataBinding does not work
Using an IEnumerable for your list of data items is not the problem, in fact the definition for the ItemsSource property on the ListBox is:
public IEnumerable ItemsSource { get; set; }
Most likely the issue is that your property is not notifying when its value has changed (use the INotifyPropertyChanged interface).
The ObservableCollection type is a collection that implements INotifyCollectionChanged, so you can easily tell when the collection itself has changed, although this doesn't notify you when the properties on the collection items themselves have changed. It also implements INotifyPropertyChanged, which is most likely why your data binding was working on your property in your ViewModel. The reason why the ObservableCollection is good to use in this case is because you can just add and remove items to the collection to update the list based control, you don't have to rebind it (or rebuild a list).
So if you bind to a IEnumerable<> property, make sure you raise a notification that the property has changed, and be aware that adding/removing individual items will not get reflected automatically in the UI unless you devise a way of notifying that the bound property has changed (which would be a bit of a hack).

Entity Framework - Code First, DbSet.Local Not Updating in UI

I have a Code First, CTP5 data context. I have a WPF app with a DataGrid. I set its DataContext like:
dataGrid.DataContext = _context.Customers.Local;
then I add a few entities using
_context.Customers.Add(customer1); and so on
_context.SaveChanges();
Then, I give these customers (a list of the customers) to another class to do some work on them.
customerUpdater.Update(customers);
That takes a long time and it updates properties of each customer while it's working. e.g.
foreach(var customer in customers) { customer.Name = "updated name"; }
I'm not seeing those updates in my WPF UI though! All I see are the original list of unaltered customers. Customers.Local is an ObservableCollection though, so I don't understand why I'm not seeing the updates in the UI.
I don't want to call SaveChanges() every time a property update occurs, it would be nearly constantly. Can someone tell me why this won't update?
If Customers.Local is an observableCollection, and you update the property "name" of one of their items, you are not seeing the updates because you are not modifying the observable collection, what you are modifying is the value of a property of one of the items (customer) present in the observableCollection, but the observableCollection will not send any notifications to the UI because it remains unchanged (it has the same number of items)
If you want the UI to be notified when you update the property name of a customer, you have to make the customer class to implement the INotifyPropertyChanged interface.
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx

How to notify all properties of the view model has changed

In MVVM pattern, how to notify all properties of the view model has changed? I don' t want to call all notifypropertychanged event of all properties.
I have an entity class and in view model I wrote all of the public fields of the entity as public properties. I want to rebind new entity and just write a single line of code to notify that all properties has changed?
Thanks for your help.
Just raise the PropertyChanged event with an empty string as the property name :
OnPropertyChanged(String.Empty);
Ok what I understood from your question is this..
View <> ViewModel <> Entity (with a bunch of properties)
View is bound to ViewModel, which delegates to Entity. You now want to replace the backing entity and signal the view to refresh to update to the newer entity.
I'd suggest implementing an indexer in the ViewModel which takes in a string (the name of the backing property). The ViewModel can be used as a cache if required, delegating to the backing entity only on a miss.
When you replace the entity, the viewModel clears its cache and fires NotifyPropertyChanged (in the indexer set) with String.Empty or null. Which I learned today, indicates all properties have changed.
This way you don't create n delegating properties in the ViewModel. A google search result shows that it has been tried at least once with success.