【问题标题】:What is the real advantage of keeping code out of the XAML code behind?将代码保留在 XAML 代码之外的真正优势是什么?
【发布时间】:2010-07-27 15:18:39
【问题描述】:

Silverlight 社区付出了很多努力来尽可能地保持 XAML 的代码隐藏在代码中。这背后的真正动机是什么?

例如,使用命令而不是事件处理程序有什么好处?如果我有

<Button x:Name="SaveButton" Content="Save" Click="SaveButton_Click" />

...

private void SaveButton_Click(object sender, RoutedEventArgs e) {
    _myViewModel.SaveChanges();
}

那为什么首选这个呢?

<Button x:Name="SaveButton" Content="Save" Command="{Binding SaveCommand}" />

显然,我的视图模型中的SaveCommand 将有效地调用SaveChanges()

这可能导致视图是 100% XAML 的情况,甚至在 XAML 中实例化视图模型,并且视图和视图模型之间的连接完全通过绑定完成。当然它很干净,但还有什么?灵活的?为什么?视图仍然需要使用正确的 ViewModel,所以如果两者之间的联系存在并且是隐式的,为什么不让它更明确呢?它还具有失去编译时支持的缺点。如果我将按钮连接到不存在的事件处理程序,编译器会告诉我。如果我绑定到不存在的命令,则不会。

【问题讨论】:

  • 我倾向于同意你的观点,如果你没有那种命令广泛有用的应用程序,那么我真的看不出额外的打字能给你带来什么。正如您所说,它不会以某种方式影响视图模型的可测试性。有些人认为,一旦您开始拥有任何代码隐藏代码,您将无法阻止自己将逻辑潜入其中,这应该在视图模型中。
  • 偏好是由于可测试性而不是 xaml/codebehind 标记。如果您的代码示例有两种方法来测试这些替代方案,那么这个问题将非常有趣。即您对 ViewModel.SaveChanges() 的测试和基于 ICommand 的测试。

标签: silverlight mvvm icommand


【解决方案1】:

在这个过程中付出了很多努力 Silverlight 社区保留 XAML 的 文件后面的代码就像免费的代码一样 可能的。真正的动机是什么 这背后?

我想说那些想要“尽可能地没有代码”背后的代码的人是那些在没有真正理解重点的情况下跳上 MVVM 潮流的人。 (或者你误解了他们的观点)。

关键不是要让代码隐藏没有代码,而是要确保 View 只负责视觉呈现。可以以声明方式定义许多视觉方面的事实意味着代码隐藏中的代码更少,但这并不意味着您应该犹豫在您认为有必要的地方编写代码隐藏并且不会超出视图的职责。

使用a有什么好处 命令而不是事件处理程序?

命令至少提供两个事件处理程序不具备的功能。一些 WPF 控件知道 Command 的 CanExecute 属性,例如,当命令不可执行时,可以禁用按钮。设计器和绑定框架也可以感知命令。

如果您只想在按下按钮时调用方法,那么使用命令而不是仅从事件处理程序调用方法会有很大的优势没有。所以不要害怕使用这种方法。 (第三种有利于设计师而不是程序员的方法是使用 Blend 4 中的 CallMethodAction)。

【讨论】:

  • 虽然我大体上同意你的观点,但我认为保持 xaml 没有代码只是为了保持分离尽可能干净是有价值的。虽然有时应该打破规则,但当你反复这样做时,很容易养成不必要地打破规则的习惯。
  • 在“XAML”中没有代码与 SoC 无关(我认为您所说的“干净分离”是指)。如果代码涉及到 View 的职责,那么您并没有违反 SoC 原则。
【解决方案2】:

它使单元测试和/或 TDD 更容易。通过使用 MVVM 和命令,我基本上可以构建我的视图模型和命令 TDD 样式,并在根本没有实际 XAML 视图的情况下测试大部分视图逻辑。

【讨论】:

  • 怎么样?你在对你的观点进行单元测试吗?我建议的任何内容都不会对视图模型产生真正的影响,使其在两种情况下都同样可测试。
  • @Matt:命令界面提供的不仅仅是一个事件。
  • 更新了我的答案...一旦 XAML 视图变为仅关于演示文稿,您可以对所有演示文稿行为进行单元测试,因为它位于视图模型和命令中。视图的视觉正确性由人类测试。
  • 好的,这有帮助。所以基本上你包括测试命令本身。这确实是有道理的,特别是如果你的命令不是微不足道的。
  • 如果答案真的是“它让测试更容易”,那么每一个好的实践和架构原则的存在都是为了“让测试更容易”。我想不是。更简单的测试是这里工作的基本原则的副作用 - 关注点分离
【解决方案3】:

您可能会听到很多关于它的论点,但实际上只有一个,可测试性。除非您为其构建单元测试,否则 ViewModel 交付很少,这反过来意味着您需要使用依赖注入、IoC、blah、blah 等技术以可以对其进行单元测试的方式创建 ViewModel等。

结果是,与保持 UI 代码更加集成的情况相比,单元测试可以覆盖应用程序代码的更大部分。

我不一定推荐它,要正确地做到这一点需要大量的设计努力和深思熟虑。因此,构建这种方法的成本相当高,但提高质量所节省的成本可能会很好地抵消这些成本。

【讨论】:

  • 当然,我会做所有这些。我对所有视图模型都有完整的单元测试。我觉得我在这里缺少一些基本的东西。视图如何回调到视图模型中似乎对测试没有太大影响。在我看来,这种方法的一个优势是使用 IoC 允许您注入虚拟数据并可能在 Blend 中以更接近实际用途的方式设计您的视图。
  • 马特你没有错过任何东西。使用事件处理程序 vs 命令不会影响可测试性。每个人都跳上了 MVVM 的潮流,他们总是在示例中使用命令,即使在许多场景中通常没有优势
【解决方案4】:

我看到该命令的主要优点是当您有执行操作的双重要求时验证该操作可以执行(即上下文)。换句话说,如果您只是将点击与直接的方法调用联系起来,我同意,我也没有看到任何优势。但是,如果应以单击为条件,并且根据上下文禁用按钮,则绑定通过 CanExecute 属性促进了这一点。

这样,我们不必担心视图中的控件(即具有“找到此控件,并将其设置为禁用,因为我们现在无法执行它)的逻辑,我们可以创建一个命令并简单地确保可以执行返回 false。这是可独立于视图进行测试的,一旦绑定它,绑定本身就会负责管理控件的 enabled 属性。

【讨论】:

    猜你喜欢
    • 2015-10-16
    • 2020-03-09
    • 2019-04-24
    • 1970-01-01
    • 2010-09-11
    • 2021-12-24
    • 2021-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多