Looking at some backbonejs examples on codeschoo.com, I don't see any explicit associations between views and their models. How does a view know what model it should be associated with? Is it by convention, e.g. TodoView assumes that this.model is of type Todo?
To explicitly set the model to the view, is it just a matter of passing in the model in the constructor?
If you pass a model property to a view constructor, it will set that directly as a property of the view instance, e.g. view.model. That's the case for a select group of other properties as well. Beyond those, properties passed to view constructors are set in view.options.
So yes, you can do this:
var view = new Backbone.View( {
model : new Backbone.Model
} );
Or change a an existing view instance's model any time by assigning to model:
view.model = new Backbone.Model;
Some people set references to views in models (e.g. model.view), but so far I've avoided that.
http://backbonejs.org/#View-constructor
When creating a new View, the options you pass are attached to the view as this.options...There are several special options that, if passed, will be attached directly to the view: model, collection, el, id, className, tagName and attributes.
Related
This is the link i am following for learning MVVM in WPF and i have a question:-
https://www.tutorialspoint.com/mvvm/mvvm_first_application.htm
DataContext of the WPF window is set to a VIEWMODEL object.
Itemsource of a List-DataTemplate is set to a List from the same VIEWMODEL Object.
The Model contains an implementation of INotifyPropertyChanged.
When i update the view,the INotifyPropertyChanged of MODEL gets fired ie VIEW is directly updating the MODEL while what i have understood till now is that VIEW interacts with the VIEWMODEL only via Bindings and Commands and never with the MODEL DIRECTLY.It is always the ViewModel which interacts with the Model to fetch data for the View.But here,the View is updating the Model DIRECTLY.This is confusing me owing to my limited knowledge.
Please guide.
If the view model exposes the model through a property, the view may actually bind directly to the model through this property. This doesn't really violate the MVVM pattern and is perfectly fine, especially if the model class implements the INotifyPropertyChanged interface. If it does, you can say that the model is kind of a (child) view model.
A "real" model such as a domain object or a service shouldn't have any knowledge about WPF and how you raise change notifications to a view. Therefore it rarely makes sense to bind directly to such objects but if your models are "WPF aware" and implements view related interfaces, you can bind to them without any issues.
It is a common error to bind the Model thru lists to the View. The correct approach would be always to create a ViewModel of that Model (the list element) and bind to it.
For example:
Otherwise you are opening the door to including data on ModelB that should be stored in the ViewModelB.
I have classes, A, B, C, D
A has a reference to E and B and to a list of C and D.
In AViewModel these are exposed in a tree.
The View for A looks like as in the picture.
When a node selected a correspondent view should be displayed.
There is ViewModels for E,B,C and D
My question is the following:
For example E is the selected node. I store it in AViewModel as "object SelectedItem".
What is the best way to create an EViewModel in a loosely coupled way, so that I do not want to reference EViewModel in AViewModel.
Update:
I was thinking about one solution, but I never seen that in other places:
For example I could expose only my POCOs (B, C, D, E) from AViewModel. And in XAML I could bind the ContentControl directly to these objects. With a converter I could have a BViewModel when I bind to B and so on.
A common and widely accepted way to communicate between view models and other components in a loosely coupled way in an MVVM application would be to use an event aggregator or a messenger. Please refer to the following links for more information.
Using the event aggregator pattern to communicate between view models: https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/
MVVM - Messenger and View Services in MVVM: https://msdn.microsoft.com/en-us/magazine/jj694937.aspx.
Another option would be to use a shared service that you inject the view models with: https://social.msdn.microsoft.com/Forums/en-US/22907a0f-d805-4195-8272-7c284b72d2ee/example-of-using-shared-services-prism?forum=wpf
Using an event aggregator, messenger or shared service means that you can remove all references between the view model classes.
Instead of the view model classes having strong references to each other back and forth, each view model only knows about a single event aggregator/messenger/shared service and communicates only with this one. View model A may send any number of messages that any other view models may subscribe to listen to and handle internally.
My question is about best practices on topic of creating an instance of a ViewModel without having a tight coupling, not about the communication between loosely coupled ViewModels
Creating an instance of another view model without creating a string coupling is impossible. If one view model creates an instance of another view model they are by definition strongly coupled. To prevent this you could inject a view model with an interface type that the other view model implements, e.g.:
public ViewModelB(IViewModelA viewModelA)
{
//...
}
Then ViewModelB is dependant on an interface type instead of a concrete implementation of the ViewModelA. It's a bit better than doing something like this because then ViewModelA and ViewModelB will always be - as mentioned above - strongly coupled to each other:
public ViewModelB()
{
_viewModelA = new ViewModellA();
}
But if you really care about loose coupling between your view model classes, you should get rid of the direct references and start to use an event aggregator or a messenger to communcate between them.
If your A View displays the "list", plus the selected view, it's perfectly acceptable to have EViewModel reference in AViewModel. ViewModels may be the "reflection" of the views. So if the A view will contain an EView, AViewModel may contain an EViewModel. You just nest your view models so it creates the same tree as in the view layer.
On top of that, what I would do is not reference E or B,... in AViewModel, but reference only EViewModel, BViewModel,... So AView list does not display model classes but ViewModel classes. Your SelectedItem gets typed as a ViewModel and you can directly bind your "Display" view part to the SelectedItem. Then you can use the right DataTemplate on the view layer to display the according view. Hope it helps
I have a nested composite view that checks its model for a collection, and if so sets that collection to itself as its collection.
onRender: ->
if model.attributes.has_collection
#collection = model.get 'myCollection'
This works quite well when the model has a collection, and the item view(s) all display, and when I add a new model to the collection, a new view appears.
However when there is no collection, and the button is clicked to create a new model, I need to create the model, set the collection (a collection of one) to the view's model, and get the view to display the model and any further models that are added. I have tried various things, right now I set the collection on the model and then run this function :
class List.myCompositeView
childView: myView
// *** //
setChildren: ->
#collection = #model.get 'myCollection'
#render()
The first model appears as it should, but further models that are created do not display. To repeat, they do appear when the collection is set in the onRender function. I realize there is lots of code that I did not add here, so if there is something (potentially) relevant to the problem that you need to know, let me know. Could it be that the view is not binding to the collection's events properly? Thanks!
A marionette collectionView has a private method called _initialEvents. When your collectionView is constructed it sets up this method to be called the first time the view is rendered. If your first render is when a collection view is not set then this would make sense that the events would not get wired up correctly. You should be able to call this private method after you set the collection and everything should work: #_initialEvents()
If it is helpful, this is the implementation of that method:
if (#collection) {
#listenTo(this.collection, 'add', #_onCollectionAdd);
#listenTo(this.collection, 'remove', #_onCollectionRemove);
#listenTo(this.collection, 'reset', #render);
if (#getOption('sort')) {
#listenTo(#collection, 'sort', #_sortViews);
}
}
I'm currently binding my WPF view directly to the 'Local' (Observable) collection of my DbSet object. ('Models' is the name of the collection in this example)
this.Models = this.context.Models.Local;
this.context.Models.Load();
this.RaisePropertyChanged(() => this.Models);
this.Models.CollectionChanged += new NotifyCollectionChangedEventHandler(ModelsChanged);
This seemed incredibly convenient, not having to move models between collections on load. The problem I'm having is the collection seemingly cannot be ordered in anyway. Not without reloading from the DB anyway. Is there a way to sort this collection or is this not what the Local collection is intended for?
It appears I can sort/filter the Local collection as follows;
ListCollectionView view = (ListCollectionView)CollectionViewSource.GetDefaultView(this.Models);
view.SortDescriptions.Add(new SortDescription("Column", ListSortDirection.Ascending));
I am working on a project using PRISM where I have left navigation implemented as Tree View and any click event happens raise event using event aggergation to Enrolment Module which has multiple view model for multiple views (like Wizard Applicaiton where you can go through many views to collect data). I want to have a common or shared or singleton model which can be passed across this view models and save at the end.... users can click on any link any navigation at any time and it should save data in to this singleton model expsosed through different view model. Do you have any samples which are doing something like this... or can you type up a quick one on how to do it? OR it is not possible to do it at all. I am following all patterns from Brian Lagunas's Pluralsight Video for PRISM so try to use that way....
I would have a MasterViewModel which controls the "wizard" pages and current state
It would contain the following properties:
List<ViewModelBase> Pages
int CurrentPageIndex
ViewModelBase CurrentPage, which returns Pages[CurrentPageIndex]
MyClass DataObject
The MasterView that goes with the MasterViewModel would be nothing more than a ContentControl with it's Content bound to CurrentPage. I would probably also define DataTemplates in the MasterView which tells WPF which View to draw with which Page
Your MasterViewModel would be in charge of handling the pages, and passing each page a reference to the data it needs. For example in the constructor it might say,
public MasterViewModel(MyClass dataObject)
{
DataObject = dataObject;
Pages.Add(new InfoPage(DataObject));
Pages.Add(new AddressPage(DataObject.Addresses));
Pages.Add(new PhonePage(DataObject.Phones));
Pages.Add(new SaveMyClassPage(DataObject));
CurrentPageIndex = 0;
}
I have an example here if you're interested
I don't know, is it prism way, or something another, when I build something like wizard, first of all I create instance of all data which wizard collect.
public WizardData wd = new WizardData();
Then, every page of wizard are initialized by this wd instance, i.e.
public FirstWizardPage(WizardData wd)
{
this.wizardData = wd;
}
So, this way allow you to have button Finish on every page, for example. You can initialize your ViewModel with wd, or its properties.
This way is not the best. Its hust one of the possible way.
Another - is to create singleton and use it without reference passing from page-to-page.
When you use Prism you also have a Dependency Injection Container, usually Unity or MEF. To solve your problem you can register your model as singleton to those DI containers. Every view model that asks the DI container to resolve their dependecy, in our special case the model, will get the singleton instance back from the DI container.
Unity example: You register your model as singleton instance:
public void Initialize( )
{
container.RegisterInstance<Model>(new Model(), new ContainerControlledLifetimeManager( ));
}
Now you can resolve your dependencies in your view model:
public ViewModel(IUnityContainer container)
{
Model model = container.Resolve<Model>();
}