有关ViewModel对简单状态

时间:2015-11-09 06:36:21

标签: wpf mvvm reactive-cocoa

我最近开始深入研究MVVM架构模式。我已经理解了它的大部分内容,但仍然很少有人怀疑 ViewModel应该代表View 承担多少责任。

换句话说,视图应该是多么愚蠢

例如,对于简单的状态协调,例如在用户按下TextView后清除SubmitButton。这种状态协调只需要使用一些流行的数据绑定框架来实现。

例如伪 - ReactiveCocoa

textView.text <~ submitButton.pressed.map { _ in "" }

然而,Martin Fowler在他的Presentation Model中写道,

  

表示模型包含的逻辑表明,只有选中复选框才能启用composer字段,因此当视图从Presentation Model更新时,composer字段控件会更改其启用状态

这表明即使按TextView后清除Button这样的简单逻辑也应封装在ViewModel内。

这样的设计选择导致类似这样的事情(再次,在伪ReactiveCocoa中):

// In View
viewModel.submitButtonPressed <~ submitButton.pressed
textView.text <~ viewModel.textViewText

// In ViewModel
textViewText <~ viewModel.submitButtonPressed.map { _ in "" }

虽然它假设视图只有绑定工作(使其变得愚蠢)时能够更好地封装逻辑,但它确实使代码更加冗长并导致View和{{1}之间更紧密的耦合(要求ViewModel了解ViewModel)。

我一般都是MVVM模式的新手,每天都在学习东西。

ViewModel应承担多少责任?

换句话说,SubmitButton必须完全愚蠢,只处理简单绑定(将其UI元素连接到View提供的可绑定属性),或者ViewModel可以公平处理像上面的简单逻辑?

另一方面,MVVM中ViewView 好的之间的紧密联系是什么?

2 个答案:

答案 0 :(得分:5)

一般来说,ViewModel承担全部责任。更具体地说,在您的方案中,ViewModel不会知道submitButton,而View会知道ViewModel会公开命令({{1}调用ICommand,并将SubmitCommand绑定到该命令。

有时可以更多地涉及完全分离动作和相应的逻辑,例如当没有可用于特定事件的命令的绑定时。但在这些情况下,一个相当简单的附加行为(即submitButton和朋友,请参阅the documentation)可以将这个差距缩小到同轴流,因此逻辑可以进入InvokeCommandAction

很少有情况(目前没有想到的),其中所以涉及到我只是跳过整个想法,并尽可能地分开,而不是必须三个月后正好到底是怎么回事。但这些案件确实很少见。

答案 1 :(得分:2)

  

换句话说,View必须完全愚蠢,只能处理简单的绑定

当视图仅包含数据绑定时,它非常好,但IRL复杂视图可以包含一些特定于视图的逻辑。例如,由于单视图模型可以连接到多个视图,因此焦点管理是视图的特权。另一个示例是“如果元素B被禁用则隐藏元素A”或“如果选中按钮则将颜色从A更改为B”等逻辑,等等。

XAML框架提供了几种技术,使视图逻辑组合得更好:命令,触发器,附加行为,值转换器。但有时你实际上需要代码隐藏。

  

例如,对于简单的状态协调,例如清除TextView   用户按下SubmitButton

更清楚。 这不是视图逻辑,必须放在视图模型中:

public class ViewModel
{
    private string someText;

    public string SomeText 
    { 
        get { return someText; }
        set
        {
            if (someText != value)
            {
                someText = value;
                OnPropertyChanged();
            }
        } 
    }

    private ICommand submitCommand;

    public ICommand SumbitCommand
    {
        if (submitCommand == null)
        {
            submitCommand = new RelayCommand(() =>
            {
                // do submit
                // clear text
                SomeProperty = null;
            });
        }
        return submitCommand;
    }
}

XAML:

<TextBox x:Name="SomeTextBox" Text="{Binding SomeText}"/>
<Button Content="Submit" Command="{Binding SubmitCommand}">

这是一个视图逻辑:

public MyWindow()
{
    InitializeComponent();
    // SomeTextBox should have initial focus
    Loaded += (sender, args) => SomeTextBox.Focus();
}
  

在MVVM中View和ViewModel之间是否紧密耦合?

理想情况下,所有组件都应松散耦合,但视图必须了解视图模型属性才能执行数据绑定。