19
votes

Let's say I have a View that is bound to ViewModel A which has an observable collection Customers.

An advantage of this MVVM pattern is that I can also bind the View to ViewModel B which fills it with different data.

But what if in my View converter Converters to display my customers, e.g. I have a "ContractToCustomerConverter" that accepts a Contract and returns the appropriate Customer to be displayed.

The problem with this is that the converter exists outside the MVVM pattern and thus doesn't know that my ViewModel has another source for customers.

  • is there a way for the View to pass the ViewModel into the Converter so that it participates in the decoupling that the MVVM pattern provides?
  • is there a way for me to somehow include the Converter in my ViewModel so that the converter uses the current dependencies which ViewModel has available?
  • or are converters just glorified code-behind and thus not used in the MVVM pattern, so if you are using MVVM then you just create your own "converters" (methods on your ViewModel class) which return things like Image objects, Visibility objects, FlowDocuments, etc. to be used on the view, instead of using converters at all?

(I came upon these questions after seeing the use of Converters in the WPF demo application that comes with the MVVM Template Toolkit download, see the "Messenger Sample" after unpacking it.)

6

6 Answers

13
votes

I usually don't use converters at all in MVVM, except for pure UI tasks (like BooleanToVisibilityConverter for instance). IMHO you should rather declare a Customer property of type CustomerViewModel in your ContractViewModel, rather than use a ContractToCustomerConverter

11
votes

In this conversation there is a comment that agrees with Kent's position, not to use Converters at all, interesting:

A ViewModel is basically a value converter on steroids. It takes "raw" data and converts it into something presentation-friendly, and vice-versa. If you ever find yourself binding an element's property to a ViewModel's property, and you're using a value converter, stop! Why not just create a property on the ViewModel that exposes the "formatted" data, and then drop the value converter altogether?

And in this conversation:

The only place I can see a use for value converters in an MVVM architecture is cross-element bindings. If I'm binding the Visibility of a panel to the IsChecked of a CheckBox, then I will need to use the BooleanToVisibilityConverter.

9
votes

Converters should rarely be used with MVVM. In fact, I strive not to use them at all. The VM should be doing everything the view needs to get its job done. If the view needs a Customer based on a Contract, there should be a Customer property on the VM that is updated by VM logic whenever the Contract changes.

An advantage of this MVVM pattern is that I can also bind the View to ViewModel B which fills it with different data.

I dispute that claim. In my experience, views are not shared across different VM types, and nor is that a goal of MVVM.

5
votes

For those effectively saying no "non-trivial converters" in the view, how do you handle the following?

Let's say that I have a Model of climate sensors that represents time series of readings from various instruments (barometer, hygrometer, thermometer, etc.) at a given location.

Let's say that my View Model exposes an observable collection of the sensors from my Model.

I have a View containing a WPF Toolkit DataGrid that binds to the View Model with the ItemsSource property set to observable collection of sensors. How do I represent the view of each instrument for a given sensor? By displaying a small graph (think Edward Tufte sparkline here) that is generated by converting the time series to an image source using a converter (TimeSeriesToSparklineConverter)

Here is how I think of MVVM: The Model exposes data to View Models. The View Model exposes behavior, Model data and state to View. Views do the job of representing Model data visually and providing an interface to behaviors consistent with the View Model state.

Thusly, I don't believe that the sparkline images go in the Model (the Model is data, not a particular visual representation of it). Nor do I believe that the sparkline images go in the View Model (what if my View wants to represent the data differently, say as a grid row just showing min, max, average, standard deviation etc. of the series?). Thus, it seems to me that the View should handle the job of transforming the data into the desired representation.

So if I want to expose the behaviors, Model data and given state for a certain View Model in a command-line interface instead of a WPF GUI, I don't want my Model nor my View Model containing images. Is this wrong? Are we to have a SensorCollectionGUIViewModel and a SensorCollectionCommandLineViewModel? That seems wrong to me: I think of the View Model as an abstract representation of the view, not concrete and tied to a particular technolgy as these names suggest they are.

That's where I am in my continually evolving understanding of MVVM. So for those saying not to use converters, what are you doing here?

1
votes

I've been using Stackoverflow for years and this is accrual my first answer posted.

I think converters belongs to View in MVVM, consider the following situation:

App is developed by 3 teams, webapi team, webclient team and UI team. UI changed frequently so the webclient team (which receives data from webapi and put them into viewmodel) cannot always modify the viewmodel to satisfy UI needs. This becomes impossible when the UI team have different versions of design. So the UI team must have their own way to present the data and the solution is Converters.

Hope this helps someone.

0
votes

I'll add my 2 cents to this discussion.

I do use converters, where it makes sense.

Explanation: There are cases where you need to represent 1 value in Model in more ways in the UI. I expose this value through 1 type. The other is type is handled through converter. If you were to expose 1 value through 2 properties in VM, you would need to manually handle update notifications.

For example I have a model with 2 ints: TotalCount, DoneCount. Now I want both this values to be displayed in TextBlocks and additionally I want to display done percentage.

I solve this using DivisionConverter multi converter which takes 2 previously mentioned ints.

If I were to have special PercentDone in VM, I would need to update this property whenever DoneCount is updated.