0

I am writing a WPF app using caliburn.micro to work with a database. I am using entity framework with the database-first approach (since I already have a db) to generate classes. Is it possible to make the entity framework gererate classes that would inherit the PropertyChangedBase class of caliburn Or to make them implement the IHandle interface. I need these classes to have it for the views to know when the data has been changed.

  • I'd recommend you keep the EF POCO models (i.e. 'Plain Old Class Object"), and have the View Model implement PropertyChangedBase, and manage whether the Model is "dirty" and out of date, or not etc. – Joe Jul 05 '17 at 14:33
  • @Joe problem with that is that if in your viewmodel you have a class that does not implement PropertyChanged, and a property of said class is changed, there will be no update about it. If you implement PropertyChanged only in the viewmodel it will only fire if you change the whole class (new or replacing the reference) – Paul Vinogradov Jul 05 '17 at 15:23
  • That's why an immutable model is even better! When does the model change currently? Surely you'd end up with different model instances (so the changes wouldn't be propagated with property notifications) from different EF dbContext anyway? – Joe Jul 05 '17 at 15:34
  • @Joe what I mean is if your vm has a property with the type of Person (a table) and you bind to person.Name (a column of said table), and you change the value of the property (Name), the viewmodel will not fire a PropertyChanged event because it thinks that the it's property (which is the Person class) never changed – Paul Vinogradov Jul 05 '17 at 16:16
  • 1
    Ah, I see. The pure MVVM way of doing it would be to mirror the properties in your VM. The model has property Name. The VM has the property Name and implements notification.This can be useful if you ever want to implement a 'save/undo'. Save applies the properties to the model, undo revers them back using the model. It's more of a pain to maintain, but after doing both I do like having that separation. Too much info I'll write an answer (even if it's not specifically an answer to the question). – Joe Jul 05 '17 at 16:27

2 Answers2

1

You could edit the copy of the .tt template inside your project:

Modifying Entity Framework Types T4 Template

The auto-generated entity classes are created using this template.

mm8
  • 163,881
  • 10
  • 57
  • 88
1

The 'pure' MVVM way of doing it (it's not set in stone and many people do implement notification in their models) would be to mirror the properties in your View Model.

Taking the Person example, your model is a simple POCO:

public class Person
{
    public String FirstName { get; set; }
    public String Surname { get; set; }
}

Your View Model translates this into something to view, a very simple version can use the 'model' as it's backing fields:

public class PersonViewModel : PropertyChangedBase
{
    private Person person;
    public Person Person
    {
        get { return person; }
        set { person = value;
              NotifyOfPropertyChange(() => FirstName);
              NotifyOfPropertyChange(() => Surname)};
    }

    public String FirstName
    {
        get { return Person.FirstName; }
        set
        {
            if (Person.FirstName != value)
            {
                Person.FirstName = value;
                NotifyOfPropertyChange(() => FirstName);
            }
        }
    }

    public String Surname
    {
        get { return Person.Surname; }
        set
        {
            if (Person.Surname != value)
            {
                Person.Surname = value;
                NotifyOfPropertyChange(() => Surname);
            }
        }
    }
}

If you're model is linked to a database through EF it is also useful when saving/loading changes etc. You can implement a save/undo or IsDirty tracking:

public class PersonViewModel : PropertyChangedBase
{
    private Person person;
    public Person Person
    {
        get { return person; }
        set { person = value; }
    }

    private String firstName;
    public String FirstName
    {
        get { return firstName; }
        set
        {
            if (firstName != value)
            {
                firstName = value;
                NotifyOfPropertyChange(() => FirstName);
            }
        }
    }

    private String surname;
    public String Surname
    {
        get { return surname; }
        set
        {
            if (surname != value)
            {
                surname = value;
                NotifyOfPropertyChange(() => Surname);
            }
        }
    }

    public void SaveToModel()
    {
        Person.FirstName = FirstName;
        Person.Surname = Surname;
        // trigger EF save?
    }

    public void LoadFromModel()
    {
        FirstName = Person.FirstName;
        Surname = Person.Surname;
    }
}

See these questions for plenty of discussion of the pros and cons of implementing PropertyChange on the Model:

MVVM duplicating Model properties in ViewModel

In MVVM model should the model implement INotifyPropertyChanged interface?

In MVVM should the ViewModel or Model implement INotifyPropertyChanged?

Having done both, I'd recommend you keep notifications out of the Model and try strive to keep it as simple as possible.

Joe
  • 6,773
  • 2
  • 47
  • 81
  • Upvote for the hard work, probably will be usefull to some new people. I have done property mirroring, but it has it's flaws. If something else (like a calculation or update background thread) has a reference to the Person object and changes his name, the PersonViewModel would not know about it because the Person itself does not fire a PropertyChanged event. When I tried having a PropertyChangedBase inherited class, all the viewmodels that have a reference update when any change to the class's properties is made. Your answer is also for a code-first approach, but i have db-first, unfortunately – Paul Vinogradov Jul 05 '17 at 17:10