【问题标题】:MVVM ViewModel interacting with View, is it true MVVM?MVVM ViewModel与View交互,是真的MVVM吗?
【发布时间】:2016-11-16 06:29:47
【问题描述】:

假设我们有一个带有 2 个选项卡和一个文件菜单的 WPF 窗口。文件菜单有两个项目“隐藏选项卡1”,“显示选项卡1”

该程序具有以下类: MainView.xaml

MainViewModel.cs

“隐藏选项卡 1”菜单命令然后绑定到 MainViewModel.cs 中包含的 HideTab1Command

HideTab1 然后直接与 View 交互以从 ViewModel 中隐藏 tab1。

这在技术上不是 MVVM 行为(更像 MVP)吗?例如,对于真正的 MVVM,执行此行为的功能应该完全包含在 XAML 代码中或 MainView.xaml.cs 中的“代码隐藏”中?

我经常看到 MVVM 应用程序和示例这样做,但它似乎违反了 SRP(单一责任原则)。

我看到其他一些应用程序使用 HideTab1 命令执行相同的操作,只是通过接口 IMainView 通知视图,然后调用 MainView.xaml.cs 中的代码

虽然我可以看到代码现在位于视图中,但这与第一个示例有何不同? SRP 仍然无效,ViewModel 告诉 View 要做什么。

这些示例中的任何一个都是真正的 MVVM 模式吗?如果不是,那么实现隐藏/显示“选项卡 1”的正确 MVVM 模式是什么。

请原谅对什么是 MVVM/MVP 的任何误解,我正在尽力正确地学习这些设计模式。

示例: ShowTab1 是一个直接操作视图的命令。我一直在 MVVM 项目中看到这一点(很多 DevExpress 示例),但它似乎没有 MVVM 的任何好处,因为您的 ViewModel 直接操纵您的视图。

MainWindow.xaml

<Window x:Class="WpfApplication.MainWindow"
    ...
        <Button Content="Show hidden panels"   Command="{Binding ShowTab1}"/>
        ...
        <TabGroup>...
    ...
</Window>

MainWindowViewMode.cs

public class MainViewModel 
{
    IMainView mainView;
    public MainViewModel()
    {
        ShowTab1 = new ShowTab1Command(this);
        mainView = ... (set this to a reference to the view)
    }

    public ICommand ShowTab1 { get; set; }
}

public class ShowTab1Command: ICommand
{
    private readonly MainViewModel _model;
    public ShowTab1Command(MainViewModel model)
    {
        _model = model;            
    }
    void ICommand.Execute(object parameter)
    {
         _model.mainView.TabGroup1MakeVisible();
    }
    bool ICommand.CanExecute(object parameter)
    {
        return true;
    }

        public event EventHandler CanExecuteChanged;

   public interface IMainView{
       public void TabGroup1MakeVisible();

真正的 MVVM 会有一个 ViewModel,纯粹用于将数据转换为视图期望的 DataContext。所有视图操作都将在视图中完成,例如在 CodeBehind 或 XAML 中。或者这是不正确的?

【问题讨论】:

  • 在没有任何实际代码的情况下很难理解您的问题。您确定可以展示一个简短的工作示例吗?
  • 如果我正确理解 HideTab1 是 ViewModel 属性 (?) 那么名称本身就不会很 MVVMish
  • HideTab1 是一个命令。例如,当您从文件菜单中单击隐藏选项卡 1 时,所需的行为是隐藏选项卡。这是一个简单的例子,不是实际的现实世界程序。我稍后会写一些内容,以便您更详细地了解我的要求。
  • 我想知道的是,除了提供数据上下文之外,是否允许视图模型中的命令与视图交互?在 mvvm 图中,它看起来好像并不意味着例如打开关闭窗口/选项卡。如果视图模型与视图交互,这似乎是 mvp,而视图模型更像是一个演示者。
  • 我添加了一个例子,请取消投票。

标签: c# wpf design-patterns mvvm mvp


【解决方案1】:

HideTab1 然后直接与 View 交互以隐藏 tab1 在 ViewModel 中。

这是程序“中断”MVVM 的地方。一个适当的解决方案是让命令更改 ViewModel 上的属性,例如:ShowTab1

在视图中,您可以将 Visibility(使用值转换器)或 IsEnabled 绑定到此属性。

这样 ViewModel 不会直接与 View 交互。

【讨论】:

  • 这是我见过的很多东西,但我所苦苦挣扎的是最终视图模型正在与视图交互(通过代理),这似乎违背了 mvvm 的目的。为什么不直接在视图中使用后面的代码,例如点击处理程序。
  • @rolls - 因为在视图中(单元)测试代码真的很难。所以我们尽量避免视图中的代码。
  • 除了单元测试还有什么其他主要原因?
  • @rolls 1. 可以在对视图模型进行重大更改的情况下更改视图。这是因为您没有按名称引用控件。 2. 视图代码很快变得比视图模型代码复杂。绑定、状态和动画系统帮助视图模型保持简单。 3. MVVM 允许您编写应用程序级代码,而无需考虑视图的行为。
  • 我完全理解使用 MVVM 的原因,我只是说在简单隐藏/显示元素(不创建或设置数据上下文)的简单情况下,为什么不使用其他所有东西在代码隐藏中完成你建议的方法?
猜你喜欢
  • 1970-01-01
  • 2011-01-17
  • 2011-09-05
  • 1970-01-01
  • 1970-01-01
  • 2011-04-09
  • 2012-09-01
  • 2013-08-29
  • 2019-01-01
相关资源
最近更新 更多