Whilst implementing my first MVVM application in WPF, I've been wondering about the pros and cons of wrapping Model collections in related ViewModel collections to use in the View.
In our system we are likely to have several potentially large collections e.g. Order Lines in an Order, and Stock Items which could be selected for an Order Line. At present these are looked up from SQL in the Data Access layer, and then SqlDataReaders are looped around to create a collection of Model Objects.
To then loop around the collection of Model objects when creating a collection of ViewModel objects seems like an unnecessary overhead. When there are large collections of Model objects would it be better to expose these directly on the View?
Thanks in advance for your help, Mark
Edit
While reading up on this subject I found this MSDN article from July this year (reviewed by Josh Smith no less) which gives a pretty balanced view of MVVM, and in the 'Collections' section said this:
Another problem with collections is
determining when or if to wrap each
Model instance in the collection
within a ViewModel instance. For
smaller collections, the ViewModel may
expose a new observable collection and
copy everything in the underlying
Model collection into the ViewModel
observable collection, wrapping each
Model item in the collection in a
corresponding ViewModel instance as it
goes. The ViewModel might need to
listen for collection-changed events
to transmit user changes back to the
underlying Model.
However, for very large collections
that will be exposed in some form of
virtualizing panel, the easiest and
most pragmatic approach is just to
expose the Model objects directly.
Thanks very much for the comments so far, trying to limit the amount of data passed into the ViewModel, or using paginated or other suitable controls would reduce problems I'm sure, but I wonder if there would there still be situations where it would be better to simply bind to a collection of Model objects within the ViewModel?
I guess that it would really depend on how you want to go about displaying the data. Afterall the ViewModel is primarily there to handle the data that the View requires.
Assuming that your data layer provides you with just the data collections you could always restrict the creation of elements within the ViewModel depending on those that you actually want to see.
For example you may have a Datagrid to display Order Items for a given Order.
Thus you could have a ViewModel Property AllOrderItems bound to the datagrid and yet its getter is as follows:
public List<OrderItems> AllOrderItems
{
get{return this.DataAccessLayer.GetOrderItems().Where(x=>x.OrderNumber==this.OrderNumber).toList();
}
Here the DataAccessLayer is a class that holds cache database data and interfaces to the database. If kept as a singleton then data duplication within it will be reduced.
You can adapt your ViewModel to do as much or as little filtering of data from the DataAccessLayer as requried. The collections can be Observable if requried and the DataAccessLayer can generate events for VMs to react to for cases of new data being added, removed, saved to the database.
Related
Using MVVM in a Silverlight project, I would like to be able to take advantage of the INotifyPropertyChanged interface by using ObservableCollections as the source of the data for a Master/Detail configuration. For the source of the Master list, I would like to use an ObservableCollection that retrieves a minimum number of fields from my database to minimixe loading time, and a different ObservableCollection for my Detail view that includes all fields for editing. Doing this with two different ObservableCollections seems to defeat the INotifyPropertyChanged advantage of using ObservableCollection since the changes are being made to a different ObservableCollection than the one used for the Master List. Is there a way to minimize data loading time for the list and still take advantage of INotifyPropertyChanged?
ObservableCollections notify upon changes in the collection - as in add/remove. They do not handle properties within the objects. The objects themselves have to implement INotifyPropertyChanged.
Objects added to the collections are added by reference. That means that if you update the object...it is updated. It won't make any difference which/how many lists contain the object.
I always find it tempting to put a model and a view-model together in one class, and I don't see the downside of doing that.
There must be a good reason for separating them. What am I missing?
ViewModel is the soft-copy of the View i.e. if you have a updateable ListBox on View, you will have an ObservableCollection in your ViewModel that represents that list of items in the listbox. Similarly if you have a Button on your View, the VM will hold its Command.
Model will be actually what has the data that the View shows. So the type collection in your VM is of, can be termed as a Model class.
E.g. a Employees ListView is a View, and has a data context which is the instance of EmployeeViewModel class that has an ObservableCollection property of Employee class where Employee class becomes a Model.
Usually there is 1-1 relationship between View and VM and 1-N relationship between VM and Model.
The model is the domain of your application and so contains your domain logic such as business rules and validations. The ViewModel is the model for your view. It handles the interactions between the user and the view, i.e. when the user clicks a button the view model will handle that interaction and may or may not make changes to the model. Normally in an OO language, you want your objects to have a single responsibility only.
In WPF the ViewModel usually implements the INotifyPropertyChange interface which is then observed by the view for any changes. You wouldn't want the model to implement this interface since it is not related to your domain in anyway.
Another reason for separation is that sometimes your view might not necessary show all data that is in the model. For example, if your model exposes 15 properties but in one of your view the user needs to see only 5 of those properties. If you place your model in the ViewModel the view would be exposed to all 15 properties whereas if you encapsulate the model in the ViewModel then only those 5 properties would be exposed to the View.
There are probably many more reasons but in general it is a good design principle to keep them separated. With that being said, if your application is small enough you can get get away with having your model and ViewModel together to reduce redundancy in your code.
The first real downside of doing this is a lack of separation of concerns. And soon this will lead to redundant code. Now, that said, I've seen a lot times where developers have used their Model objects as ViewModels. And if we're totally honest with ourselves, in a very thin app, separating these concepts can actually lead to more redundancy.
The best thing you can do is learn more about MVVM, and its roots in MVC and Presentation Model, but I think it's a great thing that you're asking this question and that you're not blindly following dogma. In fact, I often don't even start with MVVM at all when I begin a small app. I'll often start with a hundred lines or so in the code-behind, proving a concept, and then start refactoring it into MVVM.
More to the point of your question, the model and view-model have - in a conceptual sense - very different purposes. The Model includes your business logic (domain logic), data model (objects, attributes and relationships), and data access layer. The ViewModel is essentially an adaptor for the Model, adapting it for the specific purposes of the View. In some cases you might have 3 different views (and view-models) for a given data model object. Each view-model would be adapting those same attributes on the model object for the specific purposes of that particular view.
My simple answer (and I don't pretend to be WPF Guru) would be that , in WPF, you'd need a VM when:
1. You don't want to expose all your Model to a specific view
2. Your model is not in "WPF style" (doesn't implement INotifyPropertyChanged, no observable collections or no Commands).
I am trying to do some databinding magic. I have a Shipments view that lists shipments, and provides filtering and ordering ability on the list. The filter string box, Delivery Status filters (checkboxes) and Ordering Radiobuttons are databound to properties in the ViewModel. I want to add the ability to save state and I have elected to do this by saving control states in an xml document. Previously I have done this before with little problem, using databinding to just read/write the values back and forth.
However, now I have a quandry. My filter controls are currently databound to items in the ViewModel. i can write code that changes their databinding from the xml to the ViewModel on load and vice versa, but that would be messy.
Is there a mechanism in place that I can use to achieve the ability to bind to two equal sources and have them updated at the same time?
This sounds like a concern for the view model.
Why not load the saved values into the view model, and have the view model decide what data to expose?
Then the view doesn't have to be concerned with managing data.
None that I'm aware of.
My opinion: I really wouldn't do this anyway - if your datacontext is the viewmodel, and the viewmodel has properties for the filter, you almost certainly should be persisting and retrieving the relevant viewmodel state to keep the state of the filters. Trying to save controlstate, then retrieve it, set it, and set the viewmodel based on the new controlstate sounds like a lot more work and much more prone to bugs.
As I wrap my head around the mvvm thing, the view is the view, and the viewmodel is 'a modal of a view' and the model are the entities we are dealing with (or at least that is my understanding). But I'm unclear as to what and when the model entities are populated. So for example:
Lets say I have app that needs to create a new record in a DB. And that record should have default values to start with. Who is responsible for the new record, and getting the default values. Does this have anything to do with MVVM or is that part of a data access layer? Who calls the the viewmodel?
Or for existing records when\where are the records retrieved? And saved if altered?
Thanks
In an overly simplified answer, your ViewModel should contain the LOGIC for controlling what your View displays, as well as how it is allowed to interact with the Model or Data.
Events like Getting data, Saving and Deleting are intercepted through a Command mechanism and pushed into the ViewModel, where they can be tested. Handling 'Dirty' events are also the duty of the ViewModel. As for who Calls the ViewModel, you are entrusting the Calling to the Binding mechanisms available within WPF and Silverlight.
Within the ViewModel it is still about staying with best practices and ensuring that you have a DataAccess layer abstracting your Data Source and possibly using the Repository pattern to abstract that.
The life cycle of a ViewModel could be as simple as the following...
Constructor called by View
GetData method called by ViewModel Ctor
Data received and pushed into existing View databound ObservableCollection property
However since you will probably have a lot of moving parts within the Ctor of the VM, including the Data Repositories Interface you will probably want to work with an IoC. This will make the life cycle of the ViewModel closer to...
View/ViewModel (Depends if you are View or ViewModel first) is pulled out of the IoC
IoC Handles the pairing of the View-ViewModel (Convention based)
Data Repository is Injected into the ViewModel
GetData method called by ViewModel Ctor
Data received and pushed into existing View databound ObservableCollection property
This may seem like more steps, however with an IoC container you are really just calling a single method like IoC.Get(), and the rest of the steps are wired up automatically based on the conventions applied.
I use view-models to control loading (with defaults) and saving my models, and to create collections and objects that I use to bind to my views. This includes setting default values on my models.
State and Bahavior of your view is define in your viewmodel which means all events are declared here.
Who calls the the viewmodel?
it depends who needs it. you can call it in your view.
for existing records when\where are the records retrieved? And saved if altered?
saving and retrieving part is in your viewmodel.
For detailed explanation, visit this site.
Problem Statement
I'm writing a very basic WPF application to alter the contents of a configuration file. The data format is an XML file with a schema. I want to use it as a learning project for MVVM, so I have duly divided the code into
Model: C# classes auto-generated from xsd.exe
View-Model: View-friendly representation of the Model.
View: Xaml and empty code behind
I understand how the View-Model can make View-binding a breeze. However, doesn't that leave the View-Model <-> Model semantics very awkward? Xsd.exe generates C# classes with arrays for multiple XML elements. However, at the V-VM level you need Observable Collections.
Questions:
Does this really mean I have to keep two completely different collection types representing the same data in coherence?
What are the best practices for maintaining coherence between the Model and the View-Model?
I'm not a big expert, but I think that is the case yes. The general idea is indeed to propagate change between the view and the viewModel via Binding, and then between the ViewModel and the Model via events (in the Model -> ViewModel direction) or dependency (in the other direction).
I don't know how standard that is, but my understanding of MVVM is that the ViewModel should hold a reference to the model so that when the user modifies the view, the ViewModel should call the appropriate code on the model. The other way round, the Model should raise events when modified, and the ViewModel should update itself accordingly (the ViewModel being an observer to the model).
#Does this really mean I have to keep two completely different collection types representing the same data in coherence?
I think yes. It's pretty boring, but it works quite well. Hopefully, in the future we will have also a code generator to create the ViewModel part.
Karl is working on that: http://karlshifflett.wordpress.com/mvvm/
You need clearly ObservableCollections at the viewmodel so, yes, you will need two
completely different collection types in the model and in the viewmodel.
I have done an article about doing undo / redo in MVVM where you can find a possible solution to this. It uses what I call the MirrorCollection: an ObservableCollection derived class witch automatically obtains his items from a List (the list of the model).
I think it is an interesting solution, you can find the articles here
Part 1: Using the Viewmodel pattern to provide Undo / Redo in WPF
Part 2: Viewmodelling lists (here is the MirrorCollection definition)
Expose Events or delegates in Model and hook to the same in ViewModel, when ever values in the model changes notify to viewmodel via event or delegates and from Viewmodle you can update the UI.
If you want to update it from view model to model as simple as that just call some method pass the new values