Lets consider following example, I have "Document" object which contains collection of "Person" objects and each "Person" object has collection of "Address" objects. When one of the "Address" object changes I need to call server-side method to calculate optimal path between all addresses of a person(whose "Address" was changed) and update user interface. I need to know that one of addresses was changed and person whose address was changed.
The only solution I have so far is to implement some sort of event bubbling. When "Address" object changes it notifies parent("Person" object) about the change, "Person" notifies "Document". Now we can add listener to "Document" class and make required actions. Downside of this approach - I have to manage "parent" links for all the objects in the hierarchy. Can somebody comment on this solution? is it good? Or maybe I am doing something wrong here?
Thanks.
You can manage your own hierarchy using "parent" fields, or you can make the parent object listen to its children and re-dispatch events. This could probably be managed mostly via some shared helper code.
You are on the right track.
When you create the event, just set the bubbles property to true.
http://www.igorcosta.com/flex3/doc/flash/events/Event.html#bubbles
You'll have to add your event listener on the document class in ActionScript [unless you define the event metadata on the Document class], but it should work and bubble w/o problems.
If there is no compelling reason for you to "Catch / re-dispatch" I wouldn't bother to re-create the wheel.
Related
I have a parent viewmodel which has list of person which is the domain object
public class ParentViewModel
{
public List<Person> Persons{get;set;}
}
I have another viewmodels in different window which uses the person collection.
I am communicating changes by raising Prism Events. The code is bloated with if any changes are in single person or the list, the child viewmodels in different window have to bunch of stuffs.
Is there a way in WPF/.NET to track changes on person which is domain object so that I can raise prism events without going through specific code in which the person (domain object) are changed.
If i understood your need correctly then i would offer 2 options:
Use ObservableCollection instead of a List
That will make sure that whoever bind to this list is notified in case of change in the list, a good example you can read in the answer for this question.
But actually i would prefer a cleaner approach which is possible with MVVM-Light so i assume it is possible in Prism as well, and that is - Adding identifier to each person (better is when you can use one of the field as identifier). and then publish a message with the same Identifier so the listeners will subscribe to changes of a person Object with a specific Id.
in other words:
A--> Listener are subscribing to a PersonChangedMessage with a specific person identifier.
B--> Person object change - its publish a message with its identifier.
C--> Only listeners with the correspond id get notified.
A good example you can see here Subscription Filtering
Take a custom realtime object "MyObject" one property of which is an IndexReference referring to a CollaborativeList "MyList". "MyObject" also has a collaborative field property "MyProps" into which I put a json string.
In order to detect changes to "MyProps" I tried the following:
MyObject.addEventListener(gapi.drive.realtime.EventType.OBJECT_CHANGED, dealWithChanges);
However, when I make any change to an object in "MyList", which shouldn't affect the IndexReference in any way, the OBJECT_CHANGED event is fired on "MyObject"
Is this by design? It makes the OBJECT_CHANGED event useless, effectively a "something has changed somewhere" event, but without it there appears no way to detect a change to "MyProps".
Object changed events bubble, so you can listen higher up the tree for anything that is happening lower.
To listen only for changes on collaborative fields within the particular custom object, you want a ValueChangedEvent
I have created a Backbone.Collection of (say) ModelA and I am trying to listen to changes to a specific attribute of those models. This is straightforward, ...on('change:attr1'). This fires the event exactly when it needs to. The problem however is when that attribute is another model (ModelB) which has its own attributes. If an attribute of ModelB is changed, the collection won't be able to capture that event (and this is right, the attributes of ModelA never changed, the "attributes of attributes changed").
An idea is to wire-up listeners from ModelB to ModelA and then to the collection. This could work, but we are now adding a lot of listeners to build this chain of events. I also suspect that it will be a pain to unbind those listeners when we don't need them.
So is there a better way (or alternative) way of achieving this? Any feedback is appreciated.
Thanks
I think the cleanest way is to forward events through the parent model. Look at my example: http://jsfiddle.net/w8n9erqo/
But also you can override collection methods _addReference and _removeReference to add custom event binding logic. http://backbonejs.org/docs/backbone.html#section-118
Hope this helps
As the title states... how can I find a different viewmodel....
My first guess would be to search for the usercontrol it's bying used by and go through that... but it seems a lot of work for something that must be easy to find....
You can Make use of Messenger Class.
When you want to execute the method present in one Viewmodel in Other ViewModel.. You can simply send a message to the ViewModel(which holds the event you want to execute) from the ViewModel(From which you want to acess) and can execute that event.
Register the Message in the Constructor of class in which the event is declared.
Send the Message from the viewmodel(in which you want to access) at the point you want to use that event.
You probably need to use a general messaging mechanism that allows you to communicate between VM's - see MVVM Light for example
How do the two view models relate? Is one a parent of the other? In this best case scenario, you can just expose an event or delegate in one that the other subscribes to.
Similarly, if they have a common parent, this could be done in the parent view model.
If there is no relation, how about putting all common functionality into a base view model class. If the event or delegate is exposed in the base view model, then every view model that extends it can subscribe to it internally.
I have a parent view with parent model, and a child view.
I would like to pass a reference to part of the model (a collection) to the child model, so the child model can monitor this for changes and react accordingly.
I'm not sure about the best way to do this - possibly one of these approaches?
Pass whole model : I don't want to do this, as the model contains a
bunch of stuff that the child shouldn't know about.
Pass part of the model : I don't think this is possible... if I use
this.model.get('thesubpart'), I think I will be passing a value, not
a reference.
Bind the child event in the parent view : is this the way to go? I'm
not sure how I would go about doing this.
Your question is a little bit confusing, but I think you want a child model to react to something happening in a parent model, though I'm not sure if the parent is a collection or a single model itself.
The preferred way to do this is through events (i.e. parent.on('change', child.handleParentChange), where handleParentChange is a function defined on the child model. Since you seem to be interested in only a specific attribute change, you could bind to the more specific "change:thesubpart" event.
There are different ways to do this, such as an event aggregator, but the general idea is the same. Be careful of zombies, though. If the parent outlives the child, it will keep the child in memory because of the binding (an advantage of the event aggregator, if implemented correctly).