Collection change event on an attribute which is a model itself - backbone.js

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

Related

I created an event in 1 viewmodel and want another to subscribe to it, how do I find it? WPF MVVM

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.

How to access the ViewModel for a View

Let's say I have a simple View that displays a bit of text. The text comes from the View's ViewModel via a string property that is data bound. I would like to be able to set the ViewModel's string by multiple locations in the application.
What is the best practise for getting the instance of the ViewModel at the various points in my application?
I could make the ViewModel singleton but this didn't feel right.
Any suggestions?
I think there are different concepts for that.
Each has it's pros and cons....
1.) If you have have not parameters in the constructor of the view model you could use the DataContext Property of the Control, View, Page to bind the view model. It spin's up a instance per View...
2.) If you have complex or composed view models with constructor injections ... The best way would be the ViewModel Locator Pattern based on a Service Locator Pattern.
http://johnpapa.net/simple-viewmodel-locator-for-mvvm-the-patients-have-left-the-asylum
http://blog.roboblob.com/tag/viewmodellocator/
3.) you have to think about view first or view model first and maybe about something like a view model marriage...
http://wildermuth.com/2009/5/22/Which_came_first_the_View_or_the_Model
HTH
i think you looking for something like a Messenger where your viewmodel can register for messages to change your string property and other components can send a message via messenger.
another approach is the PRISM event aggregator where you can subscribe to events when your string property should be changed.
EDIT: an other but bad way would be to give an instance of your viewmodel to all other locations. but then you have no more loose coupling.

wpf MVVM ObservableCollection

My model has a couple properties one is a string and the other is an observablecolletion. When the model is created it fires off a backgroundworker thread to basically poll a .dll for data. Based on the data it receives it will either set the string and/or add and item to observable collection. My string property seems to fire its Onproperty change just fine and the view updates. However, my observable Collection throws a cross thread exception. I have tried moving code where i set the ObesrvableCollection to the worker.ReportProgress and get the same error. I have moved the logic into the view model and still get the same threading error. I'm unsure why my string property works for one. I have read about Dispatcher.Invoke, but i'm pretty sure that my model should not be aware of this. Can anyone explain the correct way to go about this please.
Just fyi - my view is not tied directly to my model. I have a property for my model in my viewModel and the model gets passed through constructor injection. Just want to put that out there before anyone thinks my model is talking directly to the the view.
Hard to give specifics without code. However, WPF automatically marshals property change notifications for scalar properties but not collections. Hence, you must be modifying the collection from a non-UI thread.
There is no reason why your VM can't use Dispatcher, or perhaps the more generic SynchronizationContext if you prefer. It can make things more tricky to test, however.
If you post code there may be a way you can simplify things.
As Kent said, if you're not on the UI you need to use the Dispatcher to update your collection:
Application.Current.Dispatcher.Invoke(new Action(() =>
{
// update your ObservableCollection here
}));

Is Events Bubbling pattern applicable to hierarchical model?

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.

CollectionViewSource Filtering Event vs Property

What are some of the practical differences between using the CollectionViewSource.View.Filter property as opposed to the CollectionViewSource.Filter event? Are there situations where you would use one over the other or is it a matter of preference?
Cheers,
Berryl
EDIT:
I do see that the docs say "If your view object comes from a CollectionViewSource object, you apply filtering logic by setting an event handler for the Filter event." although nothing stops you from setting the property on the view, and it doesn't say why to do so.
The advantage I have found so far in setting the event on the CollectionViewSource is that you can implement all of your filtering logic in one event handler and then use View.Refresh (or View.DeferRefresh) to invoke it as the user changes filtering criteria.
Setting the Filter event in the CollectionViewSource would mean that the event is called even when there is no filtering needed which would make the process less efficient.
The official way of using the Filter event is by adding it on filtering and removing it later when the filter is cleared.
viewsource.Filter += viewsource_Filter;
Then:
viewsource.Filter -= viewsource_Filter; //how do you know how many events there are!?
If you use the event, you have to make sure that you are not adding the event each time the filter value changes, because apart from having redundant events lurking around (=app works harder for nothing) you will have to remove all the events in order to clear the filter.
Thus, there is an advantage in using the Filter property, because you can more easily clear the filter by setting the property to null.
viewsource.view.Filter = null;

Resources