8

In the model tier, I have defined an enum:

public enum MemberStatus
{
    ActiveMember = 0,
    InactiveMember = 1, 
    Associate = 2,
    BoardMember = 3,
    Alumni = 4
}

In my view, I have a combo box that is populated with those enum values:

<UserControl.Resources>

  <ObjectDataProvider 
      x:Key="memberStatusesDataProvider" 
      ObjectType="{x:Type system:Enum}" 
      MethodName="GetValues">
    <ObjectDataProvider.MethodParameters>
      <x:Type TypeName="model:MemberStatus" />
    </ObjectDataProvider.MethodParameters>
  </ObjectDataProvider>

</UserControl.Resources>
...
<ComboBox 
    ItemsSource="{Binding Source={StaticResource memberStatusesDataProvider}}" 
    SelectedItem="{Binding Path=Status}" />
...

This results in getting the combo box with the choices that are exactly the same as values defined in the enum. Although that was my initial goal, I want nicer presentation for the user, something like this:

  • Combo box choices:
    • Active member
    • Inactive member
    • Associate
    • Member of the board
    • Alumni

Also, if the language in the application changes, I need the enum values in that language. To tackle this, the first thing that came to my mind is to create a converter for MemberStatus enum values. I found this beuatiful article on the topic: http://www.codeproject.com/KB/WPF/FriendlyEnums.aspx But MVVM pattern says that there should be no need to create them almost at all - and I agree with this. However, this affirmation does not work in my favor in this example.

How is it supposed to be done? Thanks.

Boris
  • 9,986
  • 34
  • 110
  • 147
  • 10
    Where did you read that MVVM requires no converters? – nlawalker Apr 18 '11 at 23:08
  • I'd be looking at a change in design rather than tweaking converters. A good solution would be to create two classes - `MemberStatus` and `AvailableMemberStatus`. `AvailableMemberStatus` would extend `List` and initialize itself in the constructor. Possibly implement as a singleton. – Greg Sansom Apr 18 '11 at 23:24
  • 1
    @nlawalker: I found it in Josh Smith's blog and several other sources. It is actually often mentioned in MVVM discussions. Personally, I agree with such statement, because the purpose of the view model is to translate the model to the view - it might prepare it for the view along the way. – Boris Apr 19 '11 at 11:27
  • 1
    I would disagree with the statement about not using converters in MVVM. WPF makes extensive use of built-in converters, and I use them regularly in my MVVM programming. I haven't had any problems with them. I take blanket statements like "But MVVM pattern says that there should be no need to create them" with a grain of salt. That is simply one person's opinion, and one with which many people disagree. – David Veeneman Aug 22 '11 at 16:16

4 Answers4

4

The view that MVVM makes value converters obsolete appears to have come from Josh Smith who says in his blog post The Philosophies of MVVM:

... a ViewModel class is essentially a value converter on steroids, thus rendering the IValueConverter interface irrelevant for most bindings.

What I take from that (and I agree with him for what it is worth) is the the View Model is responsible for all conversion from the Model's view of the world to the Views, rendering the converter obsolete.

Having an enum (which is a very data centric data type) in the Model exposed up to the UI is definitely a smell - if only for the reason you see, of showing less than ideal information to the user.

Put a mapping from enum to UI string in your View Model.

David Hall
  • 32,624
  • 10
  • 90
  • 127
  • 1
    Though - if the code is simpler and more readible, then go with the value converter approach! But the "converter on steroids" thing still stands in most cases. – David Hall Apr 18 '11 at 23:23
  • The key there is "most" bindings. There could be a case or or two where it is better to have a converter. – kevindaub Apr 19 '11 at 02:53
  • @David: Thanks for the answer. I have a problem with mapping in my situation which is explained here http://stackoverflow.com/questions/5706500/wpf-are-data-templates-obsolete-in-mvvm. So, basically, if I am relying on data templates and using model classes for their data types, I _cannot_ use the mapped property defined in view model, because that is not the data context of the template. If I should use view model properties, then the solution provided for the linked question doesn't make sense. I am in two minds here :) Please advise, thanks. – Boris Apr 19 '11 at 11:35
  • @Boris I looked at that question and agree with the commenter who mentioned having several data templates for a single VM. I haven't worked seriously in WPF for a while but remember doing this. What I can say is that if your are (as I think) binding directly to your model then this destroys the benefit of MVVM. Also, you should ideally have 1 VM per view, that handles all the translation of various model elements. I do occasionally have a VM that serves a user control in a view, but that is when the user control is essentially an isolated component. Sorry I can't offer concrete code right now – David Hall Apr 19 '11 at 21:30
  • @David That's exactly what I thought! Binding directly to the model makes no sense, MVVM wise. Also, I agree with the concept of having 1 view model per view, but also with the one of having 1 view model per an isolated component. So, to put an end to this, one final question: How do you feel with the idea of having a lot of properties in the model and mapping each of them in the view model, in order to avoid direct binding? I am asking because in many cases, it turns out that the mapping is direct, 1 to 1, which makes it look redundant (and the purpose of the pattern is to reduce redundancy). – Boris Apr 19 '11 at 22:41
  • @Boris That is possibly the number one complaint about the pattern, and one which I've yet to fully resolve in my own head. I think it really depends. If your model is rich, with a lot of logic then the isolation is good in its own regard, plus it keeps all view concerns out of the model, if the model is just a DTO then the pattern starts to become overkill. One tool to help with this is model projection AutoMapper. – David Hall Apr 19 '11 at 22:47
3

Converters are useful for way more than converting enums. Converters are also more reusable than a one-off viewmodel is.

  • I might want to convert a bool to a Brush and I can specify the parameters all in the view.

  • Or maybe I want to convert a string to DateTime and back again all via data binding. Maybe I want to convert everything to upper case. Then there is my favourite BoolToVisibilityConverter.

I'd hate to put explicit direct or indirect code all throughout my VMs just to keep some minority groups happy. The thing I would argue they forget is that converters are easily accessible from Expression Blend.

Converters are an essential part of WPF and suppliment binding between view and viewmodel.

I see no reason why you can't use them for enums.

2

MVVM is not really set in stone as to what parts of WPF are and are-not allowed. Converters are fine to use if they accomplish your goal easily. I would even suggest taking it a step further and making a MarkupExtension to supply the enum values and their string equivalents. You could store the strings in a DescriptionAttribute on each enum value.

user7116
  • 63,008
  • 17
  • 141
  • 172
  • So it's converters in the end from your perspective, right? If I understood correctly, I would do the enum value to string mapping there. Also, one more thing, I think that `DescriptionAttribute` isn't a good idea because that way the values are hard-coded. If I support different languages in the app, then the `DescriptionAttribute` would have to change dynamically. Thank you for providing your answer, cheers. – Boris Apr 19 '11 at 11:39
  • You could supply a source collection that was language aware. The markup extension I use in our product at work supports reading from a resource file to retrieve the descriptions. – user7116 Apr 19 '11 at 14:30
  • @user7116 That is ghastly and lazy. Avoid avoid avoid. resx files already achieve this. Existing localisation tools do not replace arrays of strings in attributes. – Gusdor Aug 23 '13 at 09:00
1

I don’t agree that MVVM does make ValueConverters obsolete. There are more than enough scenarios where implementing a ValueConverter makes more sense as implementing the conversion in the ViewModel class.

You might be interested in the BookLibrary sample application of the WPF Application Framework (WAF). It shows how an enum can be localized in a MVVM application. Please have a look at the BookLibrary.Presentation / Converters / LanguageToStringConverter class.

jbe
  • 6,976
  • 1
  • 43
  • 34