Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best Approach of setting the Visibility in MVVM

Tags:

mvvm

wpf

In my View I have three objects, of which one is Visible at any given time. In my Model I have an enumeration to represent the three states.

How should I implement my ViewModel?

a) Create a boolean for the visibility of each object, and bind each object to this (with a bool->visibility converter).

b) Bind to the enum, with a unique converter for each object.

c) Bind to the enum, with a single converter that takes a parameter.

d) Use a visual state manager with boolean key frames, and drive the state from VM with an attached property.

e) Bind to the VM enum from code behind, and set visibility thru code.

f) ?

I am seriously hoping the answer is f) (ie the obvious choice that escapes me), because I am not really overjoyed with a) through e).

Thoughts welcome and appreciated.

like image 922
2stroke Avatar asked Apr 04 '14 06:04

2stroke


1 Answers

The Best approach in MVVM does not necessarily mean easy. I like the following approaches:

a) Create a boolean for the visibility of each object, and bind each object to this (with a bool->visibility converter).

This method is the most intuitive and classically for setting Visibility for Control.

b) Bind to the enum, with a unique converter for each object.

c) Bind to the enum, with a single converter that takes a parameter.

In the case of the Converter, Enum is the best keep not in the Model and in the side of View. Because the problem solves over to the side of View, which is quite logical and here to store the data structure. In principle, it is not critical.

Example:

public sealed class InvertableBooleanToVisibilityConverter : IValueConverter
{
    enum Parameters
    {
        Normal, 
        Inverted
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var boolValue = (bool)value;
        var direction = (Parameters)Enum.Parse(typeof(Parameters), (string)parameter);

        if (direction == Parameters.Inverted)
            return !boolValue ? Visibility.Visible : Visibility.Collapsed;

        return boolValue ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return DependencyProperty.UnsetValue;
    }
}

A couple of comments about other approaches:

d) Use a visual state manager with boolean key frames, and drive the state from VM with an attached property.

For these situations, it looks complicated, so do not see the point in it. But, if the conditions of setting Visibility are not difficult, you can use VisualStateManager.

e) Bind to the VM enum from code behind, and set visibility thru code.

Code-behind in this case is not justified when you can solve the problem using typical tools of MVVM (Binding, Converters, etc). I think, in this case it would not be a violation of the principle of MVVM, if choosing the element to the Visibility is not involved business logic, such as may come setting Visibility by pressing of CheckBox, ToggleButton, etc.

like image 127
Anatoliy Nikolaev Avatar answered Oct 16 '22 20:10

Anatoliy Nikolaev