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).
Related
I'm currently working with a CompositeView. The problem is, when I call destroy() on one of the child views from the CollectionView part, it still remains in the this.children._view obejct, even do it disappears from the screen.
If I try to do anything with it (let's say call destroy() again) than it says, it has already been destroyed, but than why doesn't it get deleted from the object?
Thanks in advance.
Child views are not parent aware
This may sound annoying, but it's set up like that by design, since a CollectionView child may also exists on its own. As far as I can't tell children of a Collection View are not aware that they are children (except for the case that the model is destroyed [and thus removed from permanent storage]).
CollectionView.removeChildView can help
However, Marionette does expose a CollectionView method that is made exactly for what you want to do, CollectionView.removeChildView(view).
CollectionView.removeChildView will remove the view from the DOM, destroy the view (remove any listeners on the view) and remove it from the children container. Just pass in one of your views.
If you need some tips on how to trigger CollectionView.removeChildView on an event on your child view, drop me a comment.
I have a main section of code that initialises of all my views. How should I handle / listen / bind events from the main sections (probably will turn this into a main app view eventually) with elements of these initialised views? I could pass a reference of a view into another view and do something from inside that view but I'd rather have all this logic in the main / parent. Is this possible or good practice?
If they are all DOM events. No, each view should handle it's own DOM events.
If one view needs to know if something is happening in another view...well, there're lots of ways to do it. I'd usually prefer the subscriber/publisher pattern.
See my answer to another question for code examples:
Call a function in another Marionette.ItemView
You do not need Marionette for that.
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've got a parent UserControl which has a property which I would like to access from a child usercontrol of the parent.
Is this possible? I'll be doing this through the child control's viewmodel.
Just wanted to get an idea on the best approach to do this.
Thankyou.
It's not impossible, but it's not the preferred design pattern (at least not one I would happily use).
The easiest way to do this, would be to pass the parent (via reference or interface) to the child (myabe during the new routine).
The way I would do it, is to have the child raise an event (which the parent handles) when the child needs to access the parent's property. Basically, child raises event, parent handles it, by providing the necessary value to the child.
i am working on MVVM and using commanding in silverlight(DelegateEvent and ICommand)
I want something like this ,(say) i have 2 usercontrols , parent and child .
Parent is hosting the child , both have thier own viewmodels .
On parent i have a button and it executes a simple command , on execute of that command i want to update text in the child control's textbox . also we should be able to change something in child which can propagate to the parent .
Is events the best answer for this or i can have commands to update child/notify parent in some way.
There are several ways to go about this.
First, it is completely appropriate to have ViewModels that are composed of other ViewModels, as long as you are OK with them being coupled in that way. When you do that, they can just talk to each other using regular method calls.
Next, you can decouple a bit and use events. Nothing wrong with that. There is still an Observer -> Observable coupling, but they are less dependent upon each other.
Next, you can completely decouple and use something like an EventAggregator (Prism has a good one you can use). Shoot a Publish a message. The other subscribes. They don't know about each other at all.
I have used commands for this as well... but for ViewModel to ViewModel communication, I find this to be a bit awkward.
You should probably start with most obvious implementation where parent viewmodel simply holds a reference to a child viewmodel, and child viewmodel holds a reference to a parent viewmodel. Then when a command is executed on parent viewmodel it simply sets a value on a child viewmodel to which textbox is bound to.
Adding a layer of abstraction between parent and child (e.g. events) adds a level of complexity and as a result it should be justified. If the value this indirection provides is higher than the cost of increased complexity of the code (e.g. it's now less clear what happens when command on a parent is executed, you will have to solve a problem how child gets subscribed to parent's event without obtaining the actual reference to it and vice-versa, adding additional dependencies between parent a child will require adding additional events, which pollutes the actual logic with all the plumbing, etc.) then certainly events (or something like PropertyObserver) might be a next logic step.
This seems like an ideal situation for using an EventAggregator like the one in the Composite Application Guidance / Prism.
In this model, you can set up a MessageBus in the root of the application (or other common area).
// in App.xaml.cs
public static IEventAggregator MessageBus = new EventAggregator();
Then set up a common Messages library
// in Messages.cs
public class SimpleCommand: CompositePresentationEvent<SimpleObject> { }
Where SimpleObject is a class or variable that contains all the info necessary to process this event.
// in control with button
App.MessageBus.GetEvent<Messages.SimpleCommand>().Publish(SimpleObject);
// anywhere in your app that you "care" about this
App.MessageBus.GetEvent<Messages.SimpleCommand>().Subscribe(ProcessingMethod);
Where ProcessingMethod is a method that takes a SimpleObject as a parameter.
Then you can spout off messages from anywhere and process them anywhere - across viewmodels, controls, etc. You can even pass MessageBuses between components if you are dynamically loading parts of the app. Works well.