Model And ViewModel Relations and Inheritance - how should be implemented? - c#

Sorry for the confusing title of the question. I am uncertain about how should I implement ViewModels and Models which derive from a base class.
My ViewModel classes are based on a ViewModelBase, the ViewModelBase holds a ModelBase which serves as a base class for all other models.
Each ViewModel holds a "Model" Property, however, because a Model property was defined by the base ViewModel class as the ModelBase class, I always have to create another property which casts the Model - from ModelBase to the relevant Model class.
My question is - is there not a simpler solution? Is there a design pattern which is relevant for these issues?
Here's a code sample:
public abstract class BasicViewModel : ViewModelBase
{
public BasicViewModel()
{
}
public ModelBase Model { get; set; }
}
public class ModelBase
{
}
public class ContainableViewModel : BasicViewModel
{
public ContainableViewModel(ContainableModel model)
{
this.Model = model;
}
public ContainableModel MyModel { get { return (ContainableModel)Model; } }
public int Children { get { return MyModel.Children; } set { MyModel.Children = value; } }
}
public class ContainableModel : ModelBase
{
public ContainableModel()
{
Children = 2;
}
public int Children { get; set; }
}
As you can see, the "MyModel" property is the one which bugs me.
Thank you very much for your help and time!

If each of your view model contains a Model property, you could use generics:
public abstract class BasicViewModel<TModelType> : ViewModelBase
where TModelType : ModelBase
{
public BasicViewModel(TModelType model)
{
Model = model;
}
public TModelType Model { get; set; }
}
public class ModelBase
{
}
Your containable view model is now defined as follows:
public class ContainableViewModel : BasicViewModel<ContainableModel>
{
public ContainableViewModel(ContainableModel model)
: base(model)
{
}
// you can now omit this method, it is defined on the abstract superclass
//public ContainableModel Model { get { return ()Model; } }
public int Children { get { return MyModel.Children; } set { MyModel.Children = value; } }
}
public class ContainableModel : ModelBase
{
public ContainableModel()
{
Children = 2;
}
public int Children { get; set; }
}

I generally don't use a base class for the different Model types, as there is generally not a one to one correspondance between ViewModel and Model objects. Further, the Model objects generally don't have much in common. This is different from the ViewModel objects, which all tie in via data binding and therefore could benefit from various helper methods that standardize the way you bind to your ViewModel instances.
The 'Model' in Model-View-ViewModel is a layer which provides your business logic and data interaction (everything not related to visualization and interaction with the user.) Your CustomerViewModel for your CustomerWindow might make use of a Customer object from your Model layer, but it very likely has references to other objects from your model, like some sort of Repository. Other Views, like say your MainWindow, might have a MainViewModel that doesn't directly correspond to any Model object, but probably has at least a few dependencies on your Model.

Related

Problem with implementation of typed interfaces that use each other

I have two typed interfaces
public interface IComponentAreaModel<T>
public interface IComponentAreaViewModel<T>
The interface for the view model has a property 'Model' defined which is of the type of the interface for the model:
IComponentAreaModel<T> Model { get; }
In my actual implementation I have a model that implements the 'IComponentAreaModel' interface which works fine:
public class ArticleModel : IComponentAreaModel<Article>
Then I implement the view model as follows:
public class ArticleViewModel : IComponentAreaViewModel<Article>
{
public ArticleModel Model { get; }
}
And here the compiler tells me that the member 'Model' does not have the matching return type. To fix this, I would have to implement the view model as follows:
public class ArticleViewModel : IComponentAreaViewModel<Article>
{
public IComponentAreaModel<Article> Model { get; }
}
But this sucks as my ArticleModel class has some additional methods and stuff that are not part of the IComponentAreaModel. So when I wanted to use these methods through the property within my ArticleViewModel, then I would have to cast the interface object to the actual object.
Is there a way to tell the compiler that my ArticleModel implements the IComponentAreaModel and therefore is sufficient as Model for the IComponentAreaViewModel?
It depends on how do you use these interfaces. At least, there are three options.
Option 1. Use field inside implementation:
public class ArticleViewModel : IComponentAreaViewModel<Article>
{
// use this field, when you need ArticleModel
private readonly ArticleModel model;
// TODO: initialize model somehow
public IComponentAreaModel<Article> Model => model;
}
Option 2. Use explicit interface implementation:
public class ArticleViewModel : IComponentAreaViewModel<Article>
{
// use this property, when you need ArticleModel
public ArticleModel Model { get; }
IComponentAreaModel<Article> IComponentAreaViewModel<Article>.Model => Model;
}
Option 3. Add the 2nd type parameter to view model interface. Will add complexity, especially if you want to use IComponentAreaViewModel<> with another generic types:
public interface IComponentAreaViewModel<T, TModel>
where TModel : IComponentAreaModel<T>
{
TModel Model { get; }
}
public class ArticleViewModel : IComponentAreaViewModel<Article, ArticleModel>
{
public ArticleModel Model { get; }
}

How do I don't validate a nested class in FluentValidation MVC

I have a Viewmodel that have another Viewmodel inside, take a look
[Validator(typeof(ParentValidatorVM))]
public class ParentVM {
public ChildVM { get; set; }
public ParentVM () {
this.ChildVM = new ChildVM ();
}
}
//rulles for validation
internal sealed class ParentValidatorVM : AbstractValidator<ParentVM> {
public ParentValidatorVM() {
//set rules
this.RuleFor(x => x.ChildVM).NotValidate();
//the row above is just an example the method 'NotValidate', I invented
}
}
The ChildVM has the structure with properties
[Validator(typeof(ChildValidatorVM))]
public class ChildVM {
//My properties
}
//rulles for validation
internal sealed class ChildValidatorVM : AbstractValidator<ChildVM> {
public ChildValidatorVM() {
//set rules
}
}
My problem is, when I call ModelState.isValid the rules from the child comes together the rules from the Parent, it is not to happen.
Someone know a way to avoid it?

Implementing NotifyPropertyChange on EF Generated Models to achieve TwoWay binding

My goal is to do TwoWay binding off a generated EntityFramework model.
What is the best way to implement NotifyPropertyChanged on properties in a generated entity model?
For example, suppose I have this entity from a database:
public partial class Survey
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool Answer { get; set; }
}
I then create a ViewModel...
public class SurveyViewModel : ViewModelBase
{
private Survey _survey = new Survey();
public Survey
{
get { return _survey; }
set
{
_survey = value;
}
}
}
How could I achieve 2 way binding other than writing dependency properties for every single property in the entity model, like so...
//below the declaration of the Survey entity in the viewmodel
public string FirstName
{
get { return Survey.FirstName; }
set
{
Survey.FirstName = value;
NotifyPropertyChanged("FirstName");
}
}
//This works but is very time consuming for large models
Let me know if I'm attempting this wrong...
PropertyChanged.Fody may be what you are looking for:
// Non-auto generated partial class declaration
[ImplementPropertyChanged]
public partial class Survey
{
}
As commented by TyCobb, this question has been asked repeatedly and the result remains the same... here is a summary.
While there are ways pollute your data models with UI accommodating
features such as INotifyPropertyChanged, the MVVM mantra teaches us
that it is the View-Model's job to interact with the UI and the
Data-Model should remain as pure as possible (POCO).
So what? How do we keep to MVVM but avoid the boiler-plate codes of exposing individual properties on the View-Model?
From experience, calling a RaisePropertyChanged is not reserved only for property setters but could be used to manually raise a property changed for a model that has had its own properties modified, thus, cause the UI to update.
Here is a code example...
public class SurveyViewModel : INotifyPropertyChanged
{
private Survey _survey;
public Survey Survey
{
get { return _survey; }
set
{
_survey = value;
RaisePropertyChanged(() => Survey);
}
}
public void ModifySurvey()
{
// Modify a property of the model.
Survey.FirstName = "Modified";
// Make other modifications here...
// Notify property changed
RaisePropertyChanged(() => Survey);
}
}

viewmodel inheritance and duplicate model references

My question is: How to manage an inheritance chain of viewmodels?
My situation:
I'm having a standard ViewModelBase which only implements the INotifyPropertyChanged interface.
Furthermore I have a BusinessObjectViewModel which has a Guid, a PersonBaseViewModel which has the persons core data, a CustomerViewModel with customer related stuff and a EmployeeViewModel with employee related stuff.
All viewmodels certainly encapsulate a modelobject (Customer, Employee, PersonBase).
BusinessObjectViewModel inherits from ViewModelBase
PersonBaseViewModel inherits from BusinessObjectViewModel
CustomerViewModel inherits from PersonBaseViewModel
EmployeeViewModel inherits from PersonBaseViewModel
The model comes via constructor into the viewmodel.
If I use a constructor chain (every viewmodel makes a call to the base constructor) every viewmodel has it's model to return the encapsulated values from the model.
But I got to have a Model property in every viewmodel. In the case of CustomerViewModel I would have a reference in CustomerViewModel, one in PersonBaseViewModel and one in BusinessObjectViewModel for one and the same object. That sounds stupid to me.
Or I have to cast every property access in the upper viewmodels.
p.s. this is just a small cut-out of my model hierarchy.
Thanks in advance.
If BusinessObject and Person classes (and their VM counterparts) are abstract, then you could access the right Model like this:
public abstract class BusinessObjectViewModel : ViewModelBase
{
protected abstract BusinessObject BusinessObject { get; }
protected BusinessObject Model { get { return this.BusinessObject; } }
}
public abstract class PersonViewModel : BusinessObjectViewModel
{
protected abstract Person Person { get; }
protected new Person Model { get { return this.Person; } }
protected override sealed BusinessObject BusinessObject
{
get { return this.Model; }
}
}
public class CustomerViewModel : PersonViewModel
{
protected new Customer Model { get; set; }
protected override sealed Person Person
{
get { return this.Model; }
}
}
public class EmployeeViewModel : PersonViewModel
{
protected new Employee Model { get; set; }
protected override sealed Person Person
{
get { return this.Model; }
}
}
This way every derived VM class provides a value for its base VM Model property by implementing abstract property and hides a base class Model property, so every VM works with Model property of an appropriate type (so no casting is required).
This approach has its benefits and drawbacks:
Benefits:
No casting involved.
Drawbacks:
Works only if base classes (BusinessObjectViewModel and PersonViewModel) are abstract because there must exist an abstract property that is implemented by the derived class and provides a Model instance to these base classes.
Model property should not be accessed in the base class constructors, because constructor chaining goes from base class to the most derived class. The most derived class constructor will set Model, so base class constructors are called to early to see it. This can be avoided by passing Model as a parameter through constructors.
BusinessObject and Person properties are unnecessary seen by the derived classes. EditorBrowsableAttribute might help here for Intellisense, but only when code is used by another assembly in different Visual Studio solution (this is Visual Studio specific behavior).
Performance. When base classes access Model, code will go through a chain of virtual properties. But since since implemented abstract properties are marked as sealed, virtual table lookup should not be so much performance degrading.
Doesn't scale nicely. For deep class hierarchies code would contain many unnecessary members.
Another approach would be:
public class BusinessObjectViewModel : ViewModelBase
{
protected BusinessObject Model { get; private set; }
public BusinessObjectViewModel(BusinessObject model)
{
this.Model = model;
}
}
public class PersonViewModel : BusinessObjectViewModel
{
protected new Person Model { get { return (Person)base.Model; } }
public PersonViewModel(Person model)
: base(model)
{
}
}
public class CustomerViewModel : PersonViewModel
{
protected new Customer Model { get { return (Customer)base.Model; } }
public CustomerViewModel(Customer model)
: base(model)
{
}
}
public class EmployeeViewModel : PersonViewModel
{
protected new Employee Model { get { return (Employee)base.Model; } }
public EmployeeViewModel(Employee model)
: base(model)
{
}
}
Benefits:
Base classes do not need to be abstract.
Model can be accessed through base class constructors.
No unnecessary additional properties.
Drawbacks:
Casting.
Based on this analysis, I would go with a second option because fixing its only drawback, casting performance, would be unnecessary micro-optimization that would not be noticeable in WPF context.
The simplest answer IMO is to use Generics, which might be as simple as
public abstract class ViewModelBase<TModel> TModel : class{
public TModel Model { get; protected set; }
}
The .net typing system will the know that your TModel is a Person, Customer, or whatever else without casting.
Let me know if you need more or if you want to post some code that needs help. And yes, it can be tricky getting your supertype heirarchies just right at first.
HTH,
Berryl
If you just want to expose your Model property in your ViewModels then you don't need to re-declare the Model properties in the ViewModel to expose them. I normally expose the underlying Model object as a property in my ViewModels. In your case, for example in your EmployeeViewModel you would have a:
private Employee _MyEmployee;
public Employee MyEmployee {
get
{
return _MyEmployee;
}
set
{
_MyEmployee = value;
NotifyPropertyChanged(x=>x.MyEmployee);
}
Then your View could bind to your Employee properties through the MyEmployee property exposed in the ViewModel. As far as I understand it, the only case when you want to re-declare or wrap your Model Properties in your VM is when you need to do some data manipulation to be presented to your view.

Refactor my code : Avoiding casting in derived class

Firstly, I feel sorry about the title, I do not know how to describe my problem exactly. I hope it will be better explained through the code.
public abstract class AB {
public MyModel Model;
}
public class A : AB {
public A() {
Model = new MyModelA();
}
public void AMethod() {
var model = (MyModelA) model; // I have to do this all place
}
public void AnotherMethod() {
var model = (MyModelA) model; // same here
model.NewInt = 123;
}
}
public abstract class MyModel {
}
public class MyModelA : MyModel {
// new properties
public int NewInt {get;set;}
}
Take a look at the code, in order to use new properties from derived class, I have to do a cast but it is ugly when I have to use it same time all over places.
The method I think is declare another property: public MyModelA _tmp then I cast it in the constructor _tmp = (MyModelA) Model and use it instead of Model.
Are there any other appropriate ways to do this ?
Thanks !
You can make the base class generic:
public abstract class ServiceBase<TModel> where TModel : new() {
protected ServiceBase() { Model = new TModel(); }
public TModel Model { get; private set; }
}
public class AService : ServiceBase<MyModelA> {
...
}
You can maintain your Model reference in the derived class:
public abstract class AB {
public MyModel Model;
}
public class A : AB {
MyModel MyModel;
public A() {
MyModel = new MyModelA();
Model = MyModel;
}
public void AMethod() {
//just use MyModel
}
public void AnotherMethod() {
MyModel.NewInt = 123;
}
}
public abstract class MyModel {
}
public class MyModelA : MyModel {
// new properties
public int NewInt {get;set;}
}
The solution with _tmp rids you of having to write that manual cast all the time, but the problem of a strange object design remains.
I would guess your NewInt is there to perform some sort of functionality that was also present in MyModel (otherwise you'd be better off creating a new class for that to begin with). I'm wondering if you can't encapsulate that functionality in a way that MyModelA does not have to expose anything new. This may mean changing the definition of AB in order to allow for such generalizations.
The answer, I believe, is neither syntactic nor easily found in a OOP pattern without understanding the domain. Maybe you can provide some details on that.

Categories