rice
rice

Reputation: 1063

Should ViewModel have pass-through DependencyProperties that bind to DependencyProperties on the Model?

I am new to WPF/MVVM and the examples I have found do not seem to cover an issue I am facing.

I have a screen for managing a rather complex business configuration object. In MVVM I think this means I should have the following:

  1. A XAML View with close to zero logic
  2. A ViewModel class that has the screen logic
  3. My usual business classes fill the role of Model and have all business logic

In my situation there are business rules that say changes to fieldA of my business class might have various side effects, for example changing the value of fieldB, or populating an entire list of sub-objects.

I could be wrong, but I think I should keep these rules encapsulated in the business class, as these rules are not really about the screen so much as the entity.

Naturally, these side-effects need to make their way back onto the screen immediately.

So from the user's perspective, he might edit fieldA, and see fieldB updated on the View.

I understand how to databind from the View to the ViewModel.

But in my case, it seems that I need two layers of databinding: one between the View and ViewModel, and another between the ViewModel and the Model.

Given that I have essentially the same problem twice, I think one solution should apply. So I have made my Model class into a DependencyObject, and I have made its properties into DependencyProperties.

Looking at fieldA for example, it would appear in all three layers:

  1. View as a visual component databound to ViewModel.FieldA, for example text="{Binding FieldA, Mode=TwoWay}"
  2. ViewModel as a DependencyProperty bound "upward" to the View, and "downward" to the Model
  3. Model as a DependencyProperty

I prefer not to directly couple my View XAML to the business object by skipping part #2, this does not seem like a clean application of the pattern to me. Perhaps that is misguided.

I essentially seem to need a "pass-through DependencyProperty" in my ViewModel.

My questions:

Upvotes: 5

Views: 750

Answers (3)

ColinE
ColinE

Reputation: 70160

Firstly, I would not recommend using dependency properties (DP) for view models, or models. DPs are properties that have been designed with UI concepts in mind, such as precedence rules, DataContext support, default values and more. You do not need these concepts within a view models, so you should use INotifyPropertyChanged instead.

Having a view-model that is simply a pass-through to a model layer adds no value at all. So don't do it! You should never add layers, structures or concepts to your code just because you think you should. Simplicity is something that you should always strive for.

So, if you can implement a model layer, with INotifyPropertyChanged simply bind that to your view.

However ... in some cases you may not be able to implement INotifyPropertyChanged in your model. It might be generated from a web service for example. In this case you will need a view model that performs pass-through functionality, but also adds change notification via INotifyPropertyChanged.

Upvotes: 0

Dave Clemmer
Dave Clemmer

Reputation: 3781

I would agree with Steve that you should avoid using DependencyObject and DependencyProperty in your model/domain classes, and the view model classes should adopt INotifyPropertyChanged and IDataErrorInfo for binding purposes.

I would add that in your view model classes, I would avoid using DependencyProperty except for properties that you need to utilize in xaml logic, such as DataTriggers.

For handling changes that are triggered within a model layer class, I would also have a reference to the model/domain object in the view model class, and pass through getters and setters to the model/domain class just as Steve mentioned. I would add that the model/domain class will need to raise an event that the view model class will need to subscribe to, so that OnPropertyChanged() for one or more properties can be called in your view model class based on a change that happened in your business logic.

Upvotes: 0

Steve Py
Steve Py

Reputation: 35073

I struggled with this issue myself, and I imagine it is a very common snag when it comes to MVVM. My answer was to avoid polluting the domain with DependencyObject or INotifyPropertyChanged as it somewhat negates the validity of using a ViewModel.

The goal of a ViewModel is to expose a model in a manner that is relevant to a particular view. It gets confusing when the VM essentially needs to expose an entire domain object. I refer to these as "Editor" view models. These are the most tempting to pass through properties from the domain object. In these cases I give the VM a reference to a domain object (composition) and pass through getters and setters. The ViewModel adopts INotifyPropertyChanged and IDataErrorInfo rather than DependencyProperty to signal the UI if the UI needs to refresh or display validation errors. If the domain raises a validation error, then the VM catches it and prepares it into the data error info details for the view.

Upvotes: 1

Related Questions