IsDirty

Nov 19, 2010 at 5:23 AM

Is there a good way to know when any of my fields of my model have been changed? I used to set my model to "IsDirty" whenever INotifyPropertyChanged was called, but obviously I can't do that with Update Controls.

Coordinator
Nov 19, 2010 at 2:11 PM
Edited Nov 19, 2010 at 2:26 PM

One really good way to do that is to keep a copy of the original data model inside your view model.

 

public class PersonViewModel
{
    private Person _person;
    private Person _originalPerson;

    public PersonViewModel(Person person)
    {
        _person = person;
        _originalPerson = person.Copy();
    }

    public string FirstName
    {
        get { return _person.FirstName; }
        set { _person.FirstName = value; }
    }

    public string LastName
    {
        get { return _person.LastName; }
        set { _person.FirstName = value; }
    }

    public bool IsDirty
    {
        get { return !_person.Equals(_originalPerson); }
    }
}

 

If you are concerned about taking up a lot of memory, then you can use a Dependent to monitor changes. This is a little tricky.

public class PersonViewModel
{
    private Person _person;

    private Dependent _depDirty;

    public PersonViewModel(Person person)
    {
        _person = person;

        _depDirty = new Dependent(() =>
        {
            // Get the properties to set up dependency.
            string firstName = _person.FirstName;
            string lastName = _person.LastName;
        });
        // Initially bring the dependent up to date.
        _depDirty.OnGet();
    }

    public string FirstName
    {
        get { return _person.FirstName; }
        set { _person.FirstName = value; }
    }

    public string LastName
    {
        get { return _person.LastName; }
        set { _person.FirstName = value; }
    }

    public bool IsDirty
    {
        get { return !_depDirty.IsUpToDate; }
    }

    public ICommand Save
    {
        get
        {
            return MakeCommand
                .When(() => IsDirty)
                .Do(() =>
                {
                    // Save the person.

                    // Bring the dependent back up to date.
                    _depDirty.OnGet();
                });
        }
    }
}

I recommend the first option. But if you do the second, I'm not sure that the view model is the right place for it. This same code would work in your controller, model, or data access layer.

 

 

 

Coordinator
Nov 19, 2010 at 2:56 PM

Sorry. I unit tested that last recommendation before posting, but I just now tried it in a WPF app. IsUpToDate is currently not bindable. Should be an easy fix, though.

Coordinator
Nov 19, 2010 at 3:36 PM

OK, the fix is checked in. I want to test it thoroughly before I publish a new build.