views:

121

answers:

2

Here is an example case to elaborate:

I am dynamically creating a simple Bar Graph using an ItemsControl in my View and binding the items to a collection of BarViewModels (each containing percentage a value) in my BarGraphViewModel. Each bar should have a different color. The colors should be chosen from a collection e.g. {Color1, Color2, ..}

The collection itself is constant but the number of bars will depend on the circumstances.

A simple solution would be to create a simple BarViewModel like so:

public class BarViewModel
{
    public int Percentage { get; set; }

    public SolidColorBrush Stroke { get; private set; }

    public BarGraphViewModel(SolidColorBrush stroke)
    {
        Stroke = stroke;
    }
}

(I left out property changed and validation implementation for brevity)

Now I could just create a BarViewModels from my BarGraphViewModel for each percentage and pass in the appropriate ColorBrush created from my Color collection.

Then in Xaml I would create a simple ItemsTemplate that will bind to these properties.

Only now, since it contains a property of type SolidColorBrush, my ViewModel depends on the Presentation framework and should I want to use it in another environment it will have to be changed.

Does this therefore break MVVM best practices, or is it acceptable (you gotta draw the line somewhere or things get too complicated)

I just wanted to see what other people think about this and if there are other solutions that keep the ViewModel totally ignorant of the Presentation Layer without getting too complicated. I could imagine that ValueConverters could help?

+2  A: 

Teoretically, the situation you described is against the best practive in MVVM. But there is a simple solution to clean your view model up. You should create your own type for representing the color in view model - it can be string, int or enum. Then you can write custom ValueConverter (implementing IValueConverter) to convert view model color type into presentation framework dependent color representation. Converter should be used together with bounding expression. Example on converting bound values is here .

PanJanek
+1  A: 

I see no technical reasons why your VM above is bad, but would personally use a Brush rather than a specific subclass. I don't believe this breaks MVVM best practices because your VM is a model of your view. It does not necessarily have to be agnostic of the technology on which your view is built.

However, there are other reasons why it might be a bad idea. Will your view model likely be used in a non-WPF environment? If so, you'll want an abstraction that can then be translated to a platform-specific construct, with WPF's Brush being one such example. And converters aren't necessarily required for this. Your abstraction can itself be a view model, which then has platform-specific subclasses. For example, you might have a Color view model, and a WpfColor view model inheriting from that.

Do you have designers on your team? If so, the use of a Brush in your VM may inhibit their ability to customize the UI. Your specific case above may be an outlier, but generally speaking, designer and developer collaboration benefits from having the VM expose state, and the view rendering that state. As soon as the VM dictates the visual appearance in any capacity, you've limited the decisions your designers can make.

In my experience, the second reason is a far more common one not to include UI-specific constructs in your VM.

HTH,
Kent

Kent Boogaart