【问题标题】:Best Approach of setting the Visibility in MVVM在 MVVM 中设置可见性的最佳方法
【发布时间】:2014-04-04 06:32:55
【问题描述】:

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

我应该如何实现我的ViewModel

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

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

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

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

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

f) ?

我非常希望答案是 f)(即我没有想到的显而易见的选择),因为我对 a) 到 e) 并没有真正的喜出望外。

欢迎和赞赏的想法。

【问题讨论】:

  • 你能从你的模型和视图模型中显示一些代码来查看你的枚举和你的虚拟机中的使用
  • 顺便说一句,如果您的视图一次只需要一个对象,为什么您的视图模型一次没有公开一个对象?

标签: wpf mvvm


【解决方案1】:

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

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

此方法是为Control 设置可见性最直观、最经典的方法。

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

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

在转换器的情况下,Enum 最好不要放在 ModelView 旁边。因为问题解决到了 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;
    }
}

关于其他方法的几个 cmets:

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

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

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

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

【讨论】:

  • 同意,我开始编写 c) 代码,但当我意识到我的视图(转换器)正在从模型中引用我的 Enum 声明时,我很快停止了。我喜欢概念上的视觉状态方法,如果我使用不透明度而不是关键帧,xaml 就不会太可怕了。
  • @2stroke:一切皆有可能,如果条件不困难,可以使用VisualStateManager。也许我会把它添加到我的答案中。
【解决方案2】:
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.

坏主意。这不是一个好习惯。

【讨论】:

    【解决方案3】:

    除了我的评论。当我有任务根据不同的对象在视图中显示不同的内容时。我大部分时间使用内容控件和数据模板。

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

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

       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>
    

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

    【讨论】:

    • 这可能是我正在寻找的答案....我还是 WPF 的新手。在我的情况下,我希望切换的 3 个 UI 元素只是 3 个不同的标签,具有不同的内容、格式、颜色等。所以在你的示例中,我需要在我的 VM 中创建三种类型并为每个类型创建一个 DataTemplate具有必要格式的 XAML?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多