What do you do when you have Rich Models?

I work with existing code in a project that has rich models everywhere (instead of POCOs). Basically, is there a good way to combine rich models and ViewModels without repeating the code?


  • Rich models have data validation. Any easy way to reuse them using ViewModels?

Example:

public class PersonViewModel : INotifyPropertyChanged, IDataErrorInfo { private Person _person; [Required] //This seems redundent... public String FirstName { ... } } public class Person { [Required] public String FirstName { ... } } 

This is just one example ... basically, if you have a Rich Model, is there any way to take advantage of this while maintaining MVVM and avoiding redundant code? I would really like my models not to be any kind of data context or to be fully open by the ViewModel.

For instance:

 public class PersonViewModel : INotifyPropertyChanged, IDataErrorInfo { private Person _person; //This seems like a bad thing to do... public Person ThePerson { get { return _person; } } } 
+4
source share
3 answers

This is something classic.

If you "pollute" model classes with interfaces and attributes at the presentation level, you gain efficiency by having only one version of any logical model, but lose the ability to present and the business model to develop independently.

If you keep your model β€œclean” and maintain a separate viewing model, you get flexibility in each, but lose effectiveness due to the need to maintain (and correlate) two versions.

From a theoretical point of view, and for more complex systems, I would recommend the latter. If your system is relatively simple (think about CRUD) and you do not expect that you need the two types of models to evolve independently, you are probably pretty safe with the previous one.

Obviously, the two methods are not mutually exclusive, and making a decision on the screen based on the screen principle is not unheard of.

+3
source

One of the ideas of MVVM is to separate the presentation layer from the data layer. This gives you the ability to change the data that the presentation layer works with without changing the data of the data layer.

Thus, data from the presentation layer is recorded only at your data level at the request of the user. Your redundant FirstName property acts like a layer boundary, which gives you the ability to implement something like the simple "undo all changes".

Consider using a generic ValueViewModel that processes notification of changes in values, as they are necessary for data binding. After this approach, your model will look something like this:

 public class PersonViewModel : INotifyPropertyChanged, IDataErrorInfo { private Person _person; [Required] //This seems redundent... public ValueViewModel<String> FirstName { ... } } 

Using this template, your model does not need to implement the INotifyPropertyChanged interface, which again separates your presentation layer from your data layer.

MVVM is a very complex template, and you will often see things that in the first presentation seem a little formal, but after the template you will get more flexibility. If you decide to violate the MVVM rules, you are putting your entire application architecture in place because this one violation destroys the flexibility you gained with mvvm. Thus, if you plan to violate MVVM, consider not using it at all.

+1
source

I have never seen anything wrong with exposing the entire model from the ViewModel for presentation. I know this is not an "MVVM-Purist" approach, but it is simple, fast and works well.

But I understand that both methods are equally important and usually for a very large code base, that the separation between Model and ViewModel makes life easier in the long run. In that case, why don't you check the validity of the ViewModel on your ModelValidation? This is not as good as using DataAnnotations, but you will not create your validation in several places.

For example, I often use something like this:

 public string GetValidationError(string propertyName) { string s = null; switch (propertyName) { case "FirstName": case "LastName": s = Person.GetValidationError(propertyName); break; } return s; } string IDataErrorInfo.this[string propertyName] { get { return this.GetValidationError(propertyName); } } 
+1
source

All Articles