Proper MVVM ViewModel and Model pattern - c#

I haven't found an exact answer to this. Some people have mentioned that binding directly to the model as inappropriate for MVVM, however I'm trying to decide if the following pattern still follows MVVM:
View:
<TextBox Text="{Binding InfoForProcessing.BatchId}"/>
<TextBox Text="{Binding InfoForProcessing.BatchStatus}"/>
ViewModel:
private ProcessingTaskModel _infoForProcessing;
public ProcessingTaskModel InfoForProcessing
{
get
{
return _infoForProcessing;
}
private set
{
_infoForProcessing = value;
RaisePropertyChanged();
}
}
....
//doing some processing...then tell Model to populate the data:
InfoForProcessing.ResolveBatchInfo(...);
Model: (Implements INotifyPropertyChanged)
private string _batchId;
public string BatchId //VIEWABLE
{
get
{
return _batchId;
}
private set
{
_batchId = value;
RaisePropertyChanged();
}
}
private string _batchStatus;
public string BatchStatus //VIEWABLE
{
get
{
return _batchStatus;
}
private set
{
_batchStatus = value;
RaisePropertyChanged();
}
}
public bool ResolveBatchInfo(...){
//Get data from Database...
...
//Now Populate Properties with retrieved data (or return false on error)
BatchId = dr[0].ToString();
BatchStatus = dr[1].ToString();
return true;
}
I see another way to do this. I can copy those properties to the ViewModel, bind to them, and have the ViewModel populate them when returned by the Model.
For my current project here, some of the data in the Model is a dependency of queries that will be performed later
I've also made sure to encapsulate as much as possible, and only expose the properties that the View and ViewModel needs to see, while restricting setters as well.

One common stream of thinking is that - for some reason - you cannot bind directly to Model properties in your Views.
However, given that the objective of MVVM is to abstract the UI/View away from the logic, this will not be broken by bindings of this form:
{Binding ViewModel.Model.Property}
This also means you are not copying properties from Model to ViewModel all the time.

Your design, as is, is non-conforming in my opinion, as your data object contains model logic (the ResolveBatchInfo method). Here are two potential solutions:
Have seperate View Model and Model objects. In this scenario, each has their own methods. INPC for the View Model classes and database methods in the Model classes. (as shown here)
Have your POCOs "float" between layers. The important part here is that besides INPC, there is no logic in the objects, they are just data. Under this design, you would have a separate model class that encapsulates data operations and would have a method that returned populated BatchInfo objects.
I usually do (2) in my own projects, as it provides for better seperation of concerns and limits code/data replication.
Of course, with any of the three approaches (my two plus yours) the most important factor is writing code that makes sense not that it is "pure" MVVM. So go with the design that will make your life the easiest down the road.

Personally I don't mind either way, but many people (including the company who I currently work for) believe that wrapping the properties of the model, in the viewmodel is a more 'pure' approach. For me personally though, I think that it's important to think of MVVM as a guide of good practice, rather than a set of rules to be followed absolutely. I've come across instances before where I've been told to forget wrapping the properties of the model, simply because it needed to get done quickly.

Best to list this as bullets
Model DTOs can adhere to INotifyPropertyChange and be binding targets.
The VM should handle any database calls which are initiated from the View and populate stored data on the VM.
I prefer to keep my Models as POCO type entities and not the operation to get the models.
What you describe as your Model is really attributes/properties of a database operation; its status.
Short Answer
All of those items on your model should be moved and done on your VM and bound accordingly.

Related

WPF (MVVM): where to put existing "assembly" / "application logic" - in a model or viewmodel [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I have some kind of experience with WinForms coding but I am trying to do my new stuff with WPF (and the mvvm pattern).
One thing I am going round in circles for days searching the internet is to get the following right:
What do I have to implement in a model and what in the viewmodel when it goes down to "manage the repository (model?) data".
(I think) I do understand the basic concept of mvvm and decopeling all the data but I struggle to figure out the right implementation.
Let's assume I have an existing service (application without any UI) which is able to read values from a (ini) configuration file, do some stuff what its intended for, and write configurations to the local registry. Perhaps in future I want change the configuration to be stored in xml or json instead of ini. From my point of view this is all well placed in the existing code - let's say a configuration.cs file with a class configurations - which currently has absolutely nothing to do with my new wpf console application I want to implement next.
namespace ExistingConfigurationCode
{
public enum Setting
{
some,
values
}
public class ConfigurationItemProperties
{
public property1
public property 2
}
public class ApplicationConfiguration
{
List<ConfigurationItemProperties> config;
public void LoadConfig()
public void SaveConfig()
}
}
As just said, now I do want to implement a UI to enable a user to set up those configurations.
For what I have understand until now is:
the view is only the view and contains no logic at all
the viewmodel is responsible to "deliver" all needed informations to the view and receive commands from the view
the model is a model of the data we are dealing with
My problem in understanding (and knowledge how to proceed) is:
is this existing class already my model? But it does not make sense to add all the RaisePropertyChange stuff in this class because it is also used in the service. Also I have seen a lot of tutorials where I am told to not put any code in the model
if the existing class should be in my view model, what do I need the model for than?
Should the model have only a reference to my already existing class and control all read and write stuff to the registry/xml/ini through some kind of a wrapper?
Where do I have to add the "RaisePropertyChange" getter and setter? Because they are "controlling" the UI I would guess they should be placed in the view model, but I have seen a lot of examples where they are also in the model?
I got some kind of stuck here.
I thought the binding should be between the view and the view model, so the RaisePropertyChange should be in the view model, but in this case I would have to recreate everything a second time in the view model
Additional informations in response to comments
I understood now, that I can use my existing code as the model.
Besides the already existing "execution engine" which is utilizing the existing namespace/class, I have to create two applications with UI. An "admin console" and an end user console.
(I think) I am fine with the admin console, because it has a view for all the properties of ConfigurationItemProperties, so I can following Fabios first explanations.
But the second UI for the end user should have a stripped down UI, probably a listview with some checkboxes per list view item. And here is my problem.
For the listview I need the ObservableCollection, but for the items in the list view I need the "facade" fabio mentioned. Am I right so far?
If so, the ObservableCollection AND "ConfigurationItemPropertiesFacade" are working with the "model" which does not have any implementation of INotifyPropertyChanged or INotifyCollectionChanges stuff. But I think the "collections" must refer to the "single items" from the facade because the collection (from the view model) has no reference to the facade in the view model.
Try to think about MVVM like about three layers(not files) of your application.
View - namespace/project which contains only view logic(XAML and code
behind)
Model - namespace/project which contains all "business logic"
ViewModel - namespace/project which contains logic to link View and
Model without knowing about View's namespace. Another words ViewModel layer's responsibility to be a bridge between Model and View - Call Model's method, raise PropertyChanged event for when some value changed to inform View about changes.
So keep all your logic of configuration in the Model namespace.
In case when Model class need to be represent in the View with editing possibilities, create Facade class in the ViewModel layer
public class ConfigurationItemPropertiesFacade : INotifyPropertyChanged
{
private ConfigurationItemProperties _Model;
public string Property1
{
get { return _Model.Property1; }
set
{
if(Equals(_Model.Property1, value)) return;
_Model.Property1 = value;
RaisePropertyChanged();
}
}
public ConfigurationItemPropertiesFacade(ConfigurationItemProperties model)
{
_Model = model;
}
}
Use ConfigurationItemPropertiesFacade class as ViewModel in the View.
With this approach your Model layer stays clean and can be used anywhere.
In response on comment:
So tutorials telling it is not allowed to put "code" in the model are wrong, right?
Again try thinking about Model in MVVM not like a one class/file, but layer/namespace/project which can contains more then one class.
There is no right or wrong - you can implement your logic as you fill better suite your specifications. But if you will respect Single responsibility principle (https://softwareengineering.stackexchange.com/a/17170/102569), then you will separate responsibilities of ApplicationConfiguration to (I didn't know inner logic of methods Load and Save)
"Model" class which represents only data, class which has no
functionality just properties for keeping data.
You have this already ConfigurationItemProperties
"Service" classes which contains functionality of saving and loading
configurations. Your class can be spitted in two classes.
// Have one responsibility take configurations as parameter and save them somewhere
public class SaveService
{
public void Save(List<ConfigurationItemProperties> items) {}
}
// Have one responsibility load configurations and return them to the caller
public class LoadService
{
public List<ConfigurationItemProperties> Load() {}
}
So then your ViewModel will use those classes to represent and modify configurations in UI.
public class ViewModel
{
private readonly LoadService _LoadService;
private readonly SaveService _SaveService;
//Here you can use your"Facade" implementation
private ObservableCollection<ConfigurationItemPropertiesFacade> _Items
public ObservableCollection<ConfigurationItemPropertiesFacade> Items
{
get { return _Items; }
set
{
_Items = value;
RaisePropertyChanged(nameOf(Items));
}
}
public ICommand Save { get; set; }
public ICommand Load { get; set; }
public ViewModel(LoadService loadService, SaveService saveService)
{
_LoadService = loadService;
_SaveService = saveService;
// Create command instance for Save
// Create command instance for Load
var itemsList = _LoadService.Load();
var facadeItems = itemsList.Select(item => new ConfigurationItemPropertiesFacade(item));
Items = new ObservableCollection(facadeItems);
}
}
Let's think about these definitions:
Model - Data access and business Logic.
ViewModel - it's responsibility is to provide model's data and logic to view in such way that is easily consumable from view.
I believe that these definition gives you clear answer:
ExistingConfigurationCode class should be considered as part of your model.
Few more thoughts however:
INotifyPropertyChanged and INotifyCollection changed is not limited to DataBinding or WPF. These interfaces are much more general.
There nothing wrong about implementing INotifyPropertyChanged in a Model if you want your model to notify other layers or compoments about changes
It's common practice that you bind your Views directly to Model entities. ViewModel often just expose entity from Model as a property.
Wrapping model properties in ViewModel is one way of doing it. Another way is having separate properties in ViewModel with their own backing fields. You set the ViewModel properties to initial values when user visits the page and you save the edited values back to Model when user clicks save.

Should I try to "hide" the Model and ViewModel from the View?

In my Wpf project I try to seperate the view and the view-model.
I was thinking that e.g. the data-contract between view-model and model should be hidden from the view.
In practice however quite often you want to display a simple property from the data-contract in the view, which is not possible without a reference to the data-contract in the view.
E.g.
Properties.Settings.Default.Group = basedata.Groups.CurrentItem.Code;
requires a reference to the type of CurrentItem.
I could also expose a string property in the view-model like
public string CurrentGroupCode { get { return Groups.CurrentItem.Code; } }
This also looks so overdone. I tend to use the reference, because it results in less code.
Any objections?
Actually, I would go with your option 2. Why? Well if you want to implement the notification mechanism via INotifyPropertyChanged, this is the easiest way. If you want to pass values from model to the view and vice versa your example would look like this.
public SomeViewModel : ViewModelBase // assuming that you have a base class for this
{
public string CurrentGroupCode
{
get { return Groups.CurrentItem.Code; }
set
{
Groups.CurrentItem.Code = value; // assuming that the VM has been intialized correctly
RaisePropertyChanged("CurrentGroupCode"); // implemented in base class
}
}
/*
* ...Initialization, logic a.s.o.
*/
}
Means, if the business logic, which should also be implemented at the VM layer, modifies such a property, the view will be notified and updated automatically. Additionally, the modification will be propagated automatically to the model, too.
You see, with this approach you're not only hiding the model from the view, you're also providing a good modularity on the VM level, since the other VMs don't need to know something of the model structure.

MVVM: Binding to Model while keeping Model in sync with a server version

I've spent quite some time to try and find an elegant solution for the following challenge. I've been unable to find a solution that's more than a hack around the problem.
I've got a simple setup of a View, ViewModel and a Model. I will keep it very simple for the sake of explanation.
The Model has a single property called Title of type String.
The Model is the DataContext for the View.
The View has a TextBlock thats databound to Title on the Model.
The ViewModel has a method called Save() that will save the Model to a Server
The Server can push changes made to the Model
So far so good. Now there are two adjustments I need to make in order to keep the Model in sync with a Server. The type of server is not important. Just know that I need to call Save() in order to push the Model to the Server.
Adjustment 1:
The Model.Title property will need to call RaisePropertyChanged() in order to translate changes made to the Model by the Server to the View. This works nicely since the Model is the DataContext for the View
Not too bad.
Adjustment 2:
Next step is to call Save() to save changes made from the View to the Model on the Server. This is where I get stuck. I can handle the Model.PropertyChanged event on the ViewModel that calls Save() when the Model gets changed but this makes it echo changes made by the Server.
I'm looking for an elegant and logical solution and am willing to change my architecture if it makes sense.
In the past I 've written an application that supports "live" editing of data objects from multiple locations: many instances of the app can edit the same object at the same time, and when someone pushes changes to the server everyone else gets notified and (in the simplest scenario) sees those changes immediately. Here's a summary of how it was designed.
Setup
Views always bind to ViewModels. I know it's a lot of boilerplate, but binding directly to Models is not acceptable in any but the simplest scenarios; it's also not in the spirit of MVVM.
ViewModels have sole responsibility for pushing changes. This obviously includes pushing changes to the server, but it could also include pushing changes to other components of the application.
To do this, ViewModels might want to clone the Models they wrap so that they can provide transaction semantics to the rest of the app as they provide to the server (i.e. you can choose when to push changes to the rest of the app, which you cannot do if everyone directly binds to the same Model instance). Isolating changes like this requires still more work, but it also opens up powerful possibilities (e.g. undoing changes is trivial: just don't push them).
ViewModels have a dependency on some kind of Data Service. The Data Service is an application component that sits between the data store and the consumers and handles all communication between them. Whenever a ViewModel clones its Model it also subscribes to appropriate "data store changed" events that the Data Service exposes.
This allows ViewModels to be notified of changes to "their" model that other ViewModels have pushed to the data store and react appropriately. With proper abstraction, the data store can also be anything at all (e.g. a WCF service in that specific application).
Workflow
A ViewModel is created and assigned ownership of a Model. It immediately clones the Model and exposes this clone to the View. Having a dependency on the Data Service, it tells the DS that it wants to subscribe to notifications for updates this specific Model. The ViewModel does not know what it is that identifies its Model (the "primary key"), but it doesn't need to because that's a responsibility of the DS.
When the user finishes editing they interact with the View which invokes a Command on the VM. The VM then calls into the DS, pushing the changes made to its cloned Model.
The DS persists the changes and additionally raises an event that notifies all other interested VMs that changes to Model X have been made; the new version of the Model is supplied as part of the event arguments.
Other VMs that have been assigned ownership of the same Model now know that external changes have arrived. They can now decide how to update the View having all pieces of the puzzle at hand (the "previous" version of the Model, which was cloned; the "dirty" version, which is the clone; and the "current" version, which was pushed as part of the event arguments).
Notes
The Model's INotifyPropertyChanged is used only by the View; if the ViewModel wants to know whether the Model is "dirty", it can always compare the clone to the original version (if it has been kept around, which I recommend if possible).
The ViewModel pushes changes to the Server atomically, which is good because it ensures that the data store is always in a consistent state. This is a design choice, and if you want to do things differently another design would be more appropriate.
The Server can opt to not raise the "Model changed" event for the ViewModel that was responsible for this change if the ViewModel passes this as a parameter to the "push changes" call. Even if it does not, the ViewModel can choose to do nothing if it sees that the "current" version of the Model is identical to its own clone.
With enough abstraction, changes can be pushed to other processes running on other machines as easily as they can be pushed to other Views in your shell.
Hope this helps; I can offer more clarification if required.
I would suggest adding Controllers to the MVVM mix (MVCVM?) to simplify the update pattern.
The controller listens for changes at a higher level and propagates changes between the Model and ViewModel.
The basic rules to keep things clean are:
ViewModels are just dumb containers that hold a certain shape of data. They do not know where the data comes from or where it is displayed.
Views display a certain shape of data (via bindings to a view model).
They do not know where the data comes from, only how to display it.
Models supply real data. They do not know where it is consumed.
Controllers implement logic. Things like supplying the code for ICommands in VMs, listening for changes to data etc. They populate VMs from Models. It makes sense to have them listen for VM changes and update the Model.
As mentioned in another answer your DataContext should be the VM (or property of it), not the model. Pointing at a DataModel makes it hard to separate concerns (e.g. for Test Driven Development).
Most other solutions put logic in ViewModels which is "not right", but I see the benefits of controllers overlooked all the time. Darn that MVVM acronym! :)
binding model to view directly only works if the model implement INotifyPropertyChanged interface. (eg. your Model generated by Entity Framework)
Model implement INotifyPropertyChanged
you can do this.
public interface IModel : INotifyPropertyChanged //just sample model
{
public string Title { get; set; }
}
public class ViewModel : NotificationObject //prism's ViewModel
{
private IModel model;
//construct
public ViewModel(IModel model)
{
this.model = model;
this.model.PropertyChanged += new PropertyChangedEventHandler(model_PropertyChanged);
}
private void model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Title")
{
//Do something if model has changed by external service.
RaisePropertyChanged(e.PropertyName);
}
}
//....more properties
}
ViewModel as DTO
if Model implements INotifyPropertyChanged(it depends) you may use it as DataContext in most cases. but in DDD most MVVM model will be considered as EntityObject not a real Domain's Model.
more efficient way is to use ViewModel as DTO
//Option 1.ViewModel act as DTO / expose some Model's property and responsible for UI logic.
public string Title
{
get
{
// some getter logic
return string.Format("{0}", this.model.Title);
}
set
{
// if(Validate(value)) add some setter logic
this.model.Title = value;
RaisePropertyChanged(() => Title);
}
}
//Option 2.expose the Model (have self validation and implement INotifyPropertyChanged).
public IModel Model
{
get { return this.model; }
set
{
this.model = value;
RaisePropertyChanged(() => Model);
}
}
both of ViewModel's properties above can be used for Binding while not breaking MVVM pattern (pattern != rule) it really depends.
One more thing..
ViewModel has dependency on Model. if Model can be changed by external service/environment. it's "global state" that make things complicate.
If your only problem is that changes from the server get immediately re-saved, why not do something like the following:
//WARNING: typed in SO window
public class ViewModel
{
private string _title;
public string Title
{
get { return _title; }
set
{
if (value != _title)
{
_title = value;
this.OnPropertyChanged("Title");
this.BeginSaveToServer();
}
}
}
public void UpdateTitleFromServer(string newTitle)
{
_title = newTitle;
this.OnPropertyChanged("Title"); //alert the view of the change
}
}
This code manually alerts the view of the property change from the server without going through the property setter and therefore without invoking the "save to server" code.
The reason you have this problem is because your model doesn't know whether it is dirty or not.
string Title {
set {
this._title = value;
this._isDirty = true; // ??!!
}
}}
The solution is to copy the server changes via a separate method:
public void CopyFromServer(Model serverCopy)
{
this._title = serverCopy.Title;
}

Add editing to MVVM in a hierarchical data structure

This question is a follow-up of this older one, and it's more of a confirmation than an open question.
My ViewModel instance has a private instance of the Model, _modelInst.
The ViewModel has exclusive access to the Model's data during editing (so the Model doesn't need to implement INotifyPropertyChanged).
Now there are three ways I came up with how to edit the Model data from the View:
Getting/setting directly on the Model instance
e.g. for simple value fields
return _modelInst.fieldname;
_modelInst.fieldname = value;
This one's easy to implement...
Creating a ViewModel instance and operating on the parent's data structure
e.g. for more complex object types like structs:
Creating a new ViewModel for that type.
The ViewModel knows the parent and its fieldname.
displaying that in a ContentControl+DataTemplate
getting / setting:
via methods of the parent with the fieldname as parameter,
overwriting the whole original object even if only one field is changed
This means creating a new interface (with update routines working on _modelInst), implemented by the parent, for each of these structures.
Creating ViewModel instances with no direct knowledge of the parent's data structure
e.g. for (lists of) classes within parent classes
Creating a new ViewModel for each class
Sending update instructions to the parent via
commands
messages
reflection (parent knows which child called the function
by comparing the instance to all stored children)
All of these are a big mess implementing, creating functions for
every field of the model that is editable.
Which means pretty much all fields of the model...
(4.) One could create a generic ViewModel which works via reflection alone, where each
subobject knows its parent and its fieldname (+index, if in a list).
Only the root's logic would then interfere with the model.
But that solution would also require a means to store the path to a field within _modelInst.
Is there any other (more simple) way to achieve this?
Did I misunderstand the principles of MVVM (again)?
Is MVVM suited for manipulation of large hierarchical data structures?
Hopefully these resources will help; they helped me quite a bit as I learned MVVM and how to approach representing object graphs/hierarchies with view models:
Editable Object Adapter
Editable Collection Adapter
MicroModels
This is an excellent question for which I do not feel there is a good answer that comes stock with the MVC pattern.
ViewModels work great when the model they map to has no children.
But when the model has children, as in
Customer
-->Order
-->Country
(imagining Country were a child object of Customer) the design pattern kind of breaks down.
The best thing I've found is to use inheritance and selectively expose
only those children for which you need viewmodel logic. Otherwise, just access
the model's properties of the view that will come in via inheritance.
public class CustomerView : Customer //inherits from Customer (model)
{
public CustomerView(Customer customer)
{
this.FirstName = customer.FirstName
//etc..
//Only if you need it, that is if you have some display-specific
//logic relating to country for a given view, you create
//a CountryView class that inherits from Country and gets populated
//by an instance of it as well
this.CountryView = new CountryView(customer.Country)
}
public CountryView CountryView {get;set;} //sadly you cannot override Country but you may be able to shadow it.
public string DisplayColor
{
if(base.FirstName == "Joe")
{
return "red";
}
return "";
}
}
This gets messy when dealing with grandchildren. If anyone has a better solution, I would love to hear it.
Thanks

MVVM: Should a VM object expose an M object directly, or only through getters delegating to M's getters?

the best way to explain is with example so:
this is the model
public class Person
{
public int age;
public string name;
}
this is the view model
public class PersonVM
{
}
my question is:
should the vm expose the person to the data template or encapsulate the model properties with his own properties?
There is not a general agreement about that question. For example it was one of the open questions about MVVM formulated by Ward Bell here:
Is the VM allowed to offer the V an
unwrapped M-object (e.g., the raw
Employee) ? Or must the M-object’s
properties (if it is even permitted to
have properties!) be exposed
exclusively through the surface of a
VM wrapper?
The principal advantages of not directly exposing the Model in the VM are:
you can use it as a "converter on steroids", formating the model values in a convenient way for the view
you can inject other funcionality related to the user interface, like data validation messages, undo redo,..
The cons are:
you will have to duplicate a lot of code to expose all the models properties in the viewmodel.
if you bind the view control to the viewmodels property, you will send the propertyChanged events from the viewmodel. But what happens if the models property change from other source different from the viewmodel setter? Then it has to notify the viewmodel so you end with 2 OnPropertyChanged, one in the model and one in the viewmodel... quite complex!
So for me the correct answer is: it depends on your requirements.
The view model should declare its own properties and hide the specifics of the model from the view. This gives you the most flexibility, and helps keep view model-type issues from leaking into the model classes. Usually your view model classes encapsulate the model by delegation. For example,
class PersonModel {
public string Name { get; set; }
}
class PersonViewModel {
private PersonModel Person { get; set;}
public string Name { get { return this.Person.Name; } }
public bool IsSelected { get; set; } // example of state exposed by view model
public PersonViewModel(PersonModel person) {
this.Person = person;
}
}
Remember: the model shouldn't know anything about the view model that is consuming it, and the view model shouldn't know anything about the view that is consuming it. The view should know nothing about the models lurking in the background. Thus, encapsulate the model behind properties in the view model.
An interesting solution to this was proposed by Robert McCarter in MSDN volume 25.
http://msdn.microsoft.com/en-us/magazine/ff798279.aspx
He uses a dynamic View Model to provide a layer on top of the Model while avoiding proxying all of the Model properties.
If your problem space doesn't require high performance (dynamics do incur a performance hit), this is an excellent solution. The View does not need to know anything about the Model, but the View Model does not have to proxy properties that are being provided "as is." At any time properties can be added to the View Model to wrap the Model properties without modifying the View or the Model. Read the article for more details.
Having a ViewModel for any Model could be worse than that. What if you have a hierarchical structure of a Model, or even a simple collection?
In that case you'll have to iterate through all models and build a ViewModel instance per-model, and also to register notify-change events or other events. IMHO, this is completely insane, and unreasonable. As DaniCE said, you’ll end up with lot of code and a big headache.

Categories