5

I have my model all setup for my WPF application and working with entity framework ctp5 code first, here's a sample model class:

public class Task
{
    public int ID { get; set; }
    public int Index { get; set; }
    public string Content { get; set; }
    public int Indentation { get; set; }
    public DateTime Start { get; set; }
    public decimal Effort { get; set; }
    public decimal CompletedEffort { get; set; }
    public decimal Cost { get; set; }
}

What would be the recommended way to build my view model? My view models will implement INotifyPropertyChanged, I do not want the model classes to have any UI specific code - so that they can be easily reused in other apps. Should I make all of the model properties virtual then override them in the view model? (seems like a lot of unnecessary coding...) Would EF code first play nice with this type of format?

Edit This is a somewhat similar question In MVVM should the ViewModel or Model implement INotifyPropertyChanged? however, the only solutions appear to be adding in what I consider to be UI logic into the model. Perhaps I can add some sort of delegate to the model and hook into that from the viewmodel, which will in turn use INotifyPropertyChanged... something like this?

    public class Task
    {
        public delegate void HandleChange(string propertyName);
        public HandleChange ChangeHandler;

        public int ID 
        { 
            get
            {
                return ID;
            } 
            set
            {
                if(ID != value)
                {
                    ID = value;
                    ChangeHandler("ID");
                }
            }
        }
...
Community
  • 1
  • 1
Chris Klepeis
  • 9,783
  • 16
  • 83
  • 149
  • 4
    Chris, your Edit:This IS basically an implementation of `INotifyPropertyChanged`! Your delegate `HandleChange` has the same purpose as the delegate `PropertyChangedEventHandler` and the variable `ChangeHandler` has the same purpose as `PropertyChanged`. The only difference is that you don't mark ChangeHandler as `event` (which is only a protection mechanism to allow only for subscribing and unsubscribing but forbids for instance to set the handler to null). BTW: `INotifyPropertyChanged` is in Assembly `System.dll`, namespace `System.ComponentModel`; it has nothing to do with WPF or UI at all. – Slauma Feb 21 '11 at 20:53

2 Answers2

4

What I am doing is to make an instance of my model class to a property in the ViewModel and then implement INotifyPropertyChanged directly on the Model for the Model properties and on the ViewModel only for the Model instance, like so:

public class Task : INotifyPropertyChanged
{
    // Implementation of INotifyPropertyChanged
    // Raising the PropertyChanged event in the Setters of all properties
}

public class TaskViewModel : INotifyPropertyChanged
{
    private Task _task;
    public Task Task
    {
        get
        {
            return _task;
        }
        set
        {
            if (_task != value)
            {
                _task = value;
                RaisePropertyChanged("Task");
            }
        }
    }

    // INotifyPropertyChanged implementation
}

Then in XAML I bind directly to Model properties, for instance:

<TextBox Text="{Binding Task.Content}" />

(TaskViewModel would be here the DataContext for the View.)

I do this mainly to avoid this "lot of unnecessary coding" that you mention, and I could not find a drawback. (I make my model persistent with EF Code-First too.)

Slauma
  • 175,098
  • 59
  • 401
  • 420
  • @Slauna - If your model classes implement INotifyPropertyChanged then why bother with MVVM at all? The main benefit to MVVM IMO is the seperation of concerns so that the base model objects can be used in other projects more easily. My project is pretty large so I can easily imagine wanting to use the base models in WCF services , ASP.Net apps, etc... don't really want unnecessary things in there. – Chris Klepeis Feb 21 '11 at 18:10
  • It might be a valid solution in this particular case, but often you don't have the code for the model, so you can't make it implement INotifyPropertyChanged... – Thomas Levesque Feb 21 '11 at 18:11
  • 3
    @Chris: 1) INotifyPropertyChanged contains only a general .NET event which makes object changes observable from outside. I can subscribe to it in any context, not only in WPF/MVVM. This event can have its use also in other projects. If I don't need it I don't subscribe. That a model property changes IS a concern of the model, so I don't feel to violate separation of concerns. 2) Of course the ViewModels have more than only a Model instance, for example Commands which are tied to UI actions and indeed do not belong to the Model, ...(continued) – Slauma Feb 21 '11 at 18:38
  • (continue)... or other UI specific properties which are not directly mappable to Model properties. So, for all this I still need a ViewModel. Nonetheless, I can understand that you dislike this solution, I didn't like it too, before I decided to do so. But I couldn't see an alternative to either this way or copying all model properties to the ViewModel and map between Model and ViewModel property by property. My Model classes are fatter now (they also implement IDataErrorInfo), but still unrelated to WPF. – Slauma Feb 21 '11 at 18:38
  • @Slauma - Thanks for the clarification! I may end up going this route as well. – Chris Klepeis Feb 21 '11 at 18:44
  • @Chris: If you should find another way aside from this solution and copying all properties into the ViewModel, can you throw in a short comment here? I would be very interested as well ;) – Slauma Feb 21 '11 at 18:55
  • @Slauma - this appears to be a good start http://stackoverflow.com/questions/772214/in-mvvm-should-the-viewmodel-or-model-implement-inotifypropertychanged – Chris Klepeis Feb 21 '11 at 19:47
  • @Chris: That's an interesting discussion. Here I mainly agree with the answer of Paulo Sousa, especially: "However, tehre are different ways of achieving things but i would always argue in favour of simplicity and avoid redundancy." As long as I can have it simple without destroying the MVVM benefits of separation of concerns, ViewModel testability and so on, I'd do so. But it does not always work. Thomas Levesque gave a reason in his comment above when you cannot have the change notification on the model. And there may be other reasons, it always depends... – Slauma Feb 21 '11 at 20:16
3

I know this is an old thread, but I was googling about this very topic and stumbled upon this blogs.msdn.com article: http://bit.ly/iE3KHI

In short, starting with CTP 4 of EF CodeFirst there is a new property of the CodeFirst dbSet object .Local. .Local is an ObservableCollection that implements INotifyPropertyChanged. So if you have a code first dbcontext that exposes a DbSet(Of Task) called Tasks you can set your forms data context to Tasks.Local.

K4GDW
  • 195
  • 12