在MVVM中设置可见性的最佳方法

时间:2014-04-04 06:32:56

标签: wpf mvvm

在我的View我有三个对象,其中一个在任何给定时间都是可见的。在我的Model中,我有一个枚举来代表三个州。

我应该如何实施ViewModel

a)为每个对象的可见性创建一个布尔值,并将每个对象绑定到此(使用bool->可见性转换器)。

b)绑定到枚举,每个对象都有一个唯一的转换器。

c)使用带有参数的单个转换器绑定到枚举。

d)使用具有布尔关键帧的可视状态管理器,并从具有附加属性的VM驱动状态。

e)从后面的代码绑定到VM枚举,并通过代码设置可见性。

f)?

我非常希望答案是f)(即逃避我的明显选择),因为我并不喜欢a)通过e)。

欢迎和赞赏。

3 个答案:

答案 0 :(得分:3)

MVVM中的最佳方法并不一定意味着 easy 。我喜欢以下方法:

  

a)为每个对象的可见性创建一个布尔值,并将每个对象绑定到此(使用bool->可见性转换器)。

此方法对于Control设置可见性是最直观和经典的。

  

b)绑定到枚举,每个对象都有一个唯一的转换器。

     

c)使用带有参数的单个转换器绑定到枚举。

对于转换器,Enum是最好的,不在Model View 的一侧。因为问题解决了View的一面,这是非常合乎逻辑的,这里存储数据结构。原则上,它并不重要。

示例:

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;
    }
}

关于其他方法的几点评论:

  

d)使用具有布尔关键帧的可视状态管理器,并从具有附加属性的VM驱动状态。

对于这些情况,它看起来很复杂,所以不要看到它的重点。但是,如果设置可见性的条件并不困难,则可以使用VisualStateManager

  

e)从后面的代码绑定到VM枚举,并通过代码设置可见性。

当您使用MVVM(绑定,转换器等)的典型工具解决问题时,在这种情况下代码隐藏是不合理的。我认为,在这种情况下,如果选择Visibility的元素不涉及业务逻辑,那么它不会违反MVVM的原则,例如可能通过按CheckBox设置可见性, ToggleButton等等。

答案 1 :(得分:0)

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

这样我用单选按钮解决了我的问题,其中只选择了一个单选按钮。看起来更难,但你可以在以后重复使用它,如果你明白它就很容易。

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

糟糕的主意。这不是一个好习惯。

答案 2 :(得分:0)

除了我的评论。当我的任务是根据不同的对象在视图中显示不同的内容。我大部分时间都使用contentcontrol和datatemplates。

  <ContentControl Content="{Binding MyEnumObject}"/>

现在在我的viewmodel中我拥有所有不同的对象类型,并将我想要的对象设置为我的Property绑定到视图。

   private Blup _blup; //eg. is wanted when enum in model = 1

   public object MyEnumObject {get;set;}


   //set the content in your viewmodel 
   this.MyEnumObject = _blup;

现在您只需要一个数据窗口来显示您的对象

   <DataTemplate DataType="{x:Type local:Blup}">
    <view:MyBlupViewControl/>
   </DataTemplate>

但也许我完全错了。但是你的实际问题需要很大的解释空间