Using a non-anemic domain model with Wpf MVVM

I am using a WPF based application using MVVM for the user interface.

I have a ViewModel that wraps every editable model that can be edited. VM contains all error notification processing logic, dirty management, etc.

This design supports CRUD scripting schemes for simple domain model objects that are anemic , that is, do not contain any logic.

Now I am faced with a more complex problem: I have a domain model that contains logic, and this logic can change the internal state of the domain model.

Has anyone already encountered this scenario? If so, do you have any tips for proper handling?

Riana

+5
source share
3 answers

This is how I usually deal with this:

  • The ViewModel level consists of types that belong to this layer, which means that I never use my business objects inside the ViewModel. I map my business objects to ViewModel objects, which may or may not be the exact same form minus the behavior. It can be argued that this violates Do not repeat Yourself, but it allows you to adhere to the principle of single responsibility. In my opinion, SRP should usually narrow DRY. The ViewModel exists to serve the view, and the model exists to serve the business rules / behavior.

  • /, ViewModels , ViewModels -- -. , - ViewModel

: ViewModel ↔ Facade/ServiceLayer → -

, , MVVM: ViewModel - / , , .

+9

. , () . , ViewModel , . ​​ () .

ViewModels ( ), .

+2

, ViewModel. , , , .

:

:

public class NonAnemicModel
{
    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            if (_name == value)
                return;

            _name = value;
            OnNameChanged(EventArgs.Empty);
        }
    }

    public event EventHandler NameChanged;
    protected virtual void OnNameChanged(EventArgs e)
    {
        if (NameChanged != null)
            NameChanged(this, e);
    }

    public void PerformNameCalculation(int chars)
    {
        //example of a complex logic that inadvertently changes the name
        this.Name = new String('Z', chars); //makes a name of Z's
    }
}

ViewModel:

public class MyViewModel : INotifyPropertyChanged
{
    private NonAnemicModel _model;

    public NonAnemicModel Model 
    {
        get { return _model; }
        set
        {
            _model = value;
            _model.NameChanged += (sender, args) => NotifyPropertyChanged("UserName");
        }
    }

    public string UserName 
    {
        get { return this.Model.Name; }
        set { this.Model.Name = value; }
    }

    //this command would call out to the PerformNameCalculation method on the Model.
    public ICommand PerformNameCalculation { get; private set; }
}

, PropertyChanged . , , UserName PerformNameCalculation, ViewModel . , , , . !

+1

All Articles