MVVM ViewModel 是否应该执行类型转换/验证? [英] Should the MVVM ViewModel perform type conversion/validation?

查看:41
本文介绍了MVVM ViewModel 是否应该执行类型转换/验证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们刚刚进入 WPF 中的 MVVM.

We're just getting into MVVM in WPF.

我们已经使用我们在视图中绑定的强类型"属性(int、double?等)实现了我们的 ViewModel.

We have implemented our ViewModels with 'strongly typed' properties (int, double? etc.) that we bind to in the view.

大多数情况下,类型转换工作正常,因此输入数据非常简单.但是我们遇到了验证问题.

Type conversion works OK, mostly, and so entering data is simple enough. But we run into problems with validation.

如果在绑定到数字属性的文本框中输入非数字值,则转换失败,该属性永远不会被设置,我们也永远没有机会向用户提供适当的反馈.更糟糕的是,该属性会保留其当前值,从而导致视图中显示的内容与 ViewModel 中的实际内容不匹配.

If, say, a non-numeric value is entered in a text box bound to a numeric property, the conversion fails, the property is never set, and we never get a chance to provide proper feedback to the user. Worse, the property retains its current value, leading to a mismatch between what's displayed in the view and what's actually in the ViewModel.

我知道,所有这些都可以通过值转换器来处理.但是我看到了一些意见,大意是转换根本不应该是视图的责任.视图中输入的是字符串,转换、验证等应该是 ViewModel 的责任(所以论点).

All this can be handled with value converters, I know. But I have seen several opinions to the effect that conversion should not be the view's responsibility at all. What is entered in the view are strings, and the conversion, validation etc. should be the ViewModel's responsibility (so the argument goes).

如果是这样,我们应该将 ViewModel 上的大部分属性重写为字符串,并通过 IErrorInfo 接口提供错误信息,例如.它肯定会使视图中的 XAML 变得更简单、更精简.另一方面,从视图设计者的角度来看,转换、验证等将不那么具有声明性、明确性和灵活性.

If so, we should rewrite most of the properties on our ViewModels to string, and provide error information through the IErrorInfo interface, for example. It would surely make for simpler, leaner XAML in the view. On the other hand, conversion, validation etc. will be less declarative, explicit and flexible, from the point of view of the View designer.

在我们看来,这两种方法根本不同,因此在我们做出决定之前,我们希望对此事有一些知情的 SO 意见.

It seems to us these two approaches are fundamentally different, so before we decide, we'd like some informed SO opinions on the matter.

那么:ViewModel 是否应该向视图公开一个简化的、基于文本的"界面并在内部处理转换?还是应该 ViewModel 属性公开实际的数据类型,将这些杂事留给视图来处理?

So: should ViewModels expose a simplified, 'text-based' interface to the view and handle conversion internally? Or should ViewModel properties expose the actual data types, leaving such chores to the view to handle?

更新:

在这里很难选出一个赢家,但我终于找到了一个或多或少像我一样得出结论的人.

Hard to pick a winner here, but I finally landed on one of you who concludes more or less like myself.

具体来说,我们决定保留 ViewModel 属性的类型.这样做的主要原因是它为我们提供了设计视图的灵活性,以及​​ XAML 中显式、声明性转换/格式的强大功能.

Specifically, we have decided to keep the ViewModel properties typed. The main reason for this is the flexibility it affords us in the design of the view, and the power of explicit, declarative conversion/formatting in XAML.

我注意到你的一个假设,他会不同意我们的观点,即视图的设计是固定的并准备就绪.因此,不需要在视图中做出关于转换、格式等的决定.但我们的流程是敏捷的,我们还没有事先弄清楚 UI 的所有细节.

I noticed an assumption with you who will disagree with us in this, that the design of the view is fixed and ready. Hence, no decisions about conversion, formatting etc. need be made in the view. But ours is an agile process, and we haven't got all the nitty gritty detail of the UI figured out on beforehand.

事实上,让 UI 的细节在整个过程中都被设计出来为创意留下了空间,此外,在我看来,即使是精心设计的设计也会在整个实施过程中最终发生变化.

In fact, leaving the details of the UI to be worked out along the way leaves room for creativity and besides, in my opinion, even a meticulously worked out design will always end up morphing throughout the implementation process.

所有这一切的重点是,虽然业务规则执行肯定属于 ViewModel,但在我们看来,简单的转换和格式化是一种视图.这听起来像是异端邪说,但我实际上并不认为视图中的类型转换根本不需要单元测试(只要我们对实际的类型转换器进行单元测试).

The point of all this is that whereas business rules enforcement certainly belongs in the ViewModel, it seems to us that simple conversion and formatting is a view-thing. It may sound like heresy, but I don't actually think type conversion in the view needs unit testing at all (so long av we unit test the actual type converters).

总而言之,这是一场精彩的讨论,大家都提出了精心制定、知情的意见.谢谢.

All in all a great discussion, folks, with well formulated, informed opinions. Thanks.

推荐答案

这是一个非常有趣的问题,我觉得这个问题没有明确的答案,但我会尽我所能把我的想法抛诸脑后.

This is a very interesting question and one that I don't feel has a definitive answer, but I'll do my best to throw my thoughts out there.

按照我的理解,查看 MVVM 模式,ViewModel 的重点是以视图可以理解的方式公开数据, 对视图将使用它的方式没有任何假设.例如,让我们假设我们正在模拟汽车的速度:

Looking at the MVVM pattern as I understand it, the point of the ViewModel is to expose the data in a way the View can understand without any assumptions about the way the view is going to use it. For an example let's pretend that we are modelling the speed of a car:

public class CarModel
{
    public int MilesPerHour { get; set; }
}

public class CarViewModel
{
    private CarModel _model;

    public int MilesPerHour
    {
        get { return _model.MilesPerHour; }
        set { _model.MilesPerHour = value; }
    }
}

在上面的示例中,我将属性作为 int 公开,因为这就是模型中的内容.您在问题中列出了这样做的缺点,但主要优点是它为视图的创建者提供了有关如何显示该数据的宝贵信息.请记住,我们(作为 ViewModel 的作者)不知道 View 是什么样子.通过将数据视为 int 的想法,视图可以使用文本框或其他仅接受数字(例如拨号)的控件来显示信息.如果我们说我们要以一种我们假定对视图有帮助的方式格式化数据,那么它就会失去它的重要力量.

In the example above I've exposed the property as an int since that is what it is in the model. The disadvantages of this you have listed in your question, but the main advantage is that it gives the creator of the view a valuable piece of information about how to display that data. Remember that we (as the authors of the ViewModel) don't know what the View looks like. By committing to the idea of the data being an int the View can use a textbox or some other control that only accepts numbers (a dial, for example) to display the information. If we say that we are going to format the data in a way that we assume is helpful to the View it takes that important power away from it.

另一方面,我们在现实世界中工作.我们往往知道什么是视图.我们很少在同一个 ViewModel 之上插入和播放不同的视图,并且将转换代码添加到 ViewModel 中更容易.我不认为这是正确的,但这并不意味着你不会找到我使用它的生产代码......

On the other hand we work in real world. We tend to know what the view is. We rarely plug and play different views on top of the same ViewModel and adding the conversion code into the ViewModel is simply easier. I don't think it is right, but that doesn't mean you won't find my production code using it...

最后(我相信你知道这一点,但为了完成......)业务逻辑应该在 ViewModel 中完成.如果我们决定汽车的时速不应超过 70 英里/小时,那么强制执行这一点就不是视图的责任.所以你最终还是会得到某种错误提供者,但在业务层面而不是显示层面.

Finally (and I'm sure you know this, but for completions sake...) business logic should be done in the ViewModel. If we decide that the car shouldn't go above 70mph then it isn't the responsibility of the view to enforce that. So you'll still end up with some kind of error provider, but at a business rather than display level.

好吧,也许最后还没有......

Okay, maybe that wasn't finally....

我想解决 Kent 的评论,但我的想法不适合评论.

I wanted to address the comments made by Kent, and my thoughts didn't fit into a comment.

显然,我和 Kent 的观点之间的主要区别(据我所知)是他将 ViewModel 读为视图的模型,而我将其读为将模型暴露给视图的东西.我承认有一个细微的差别,但我认为结果是我不想删除模型提供的信息,即使它使我正在使用的特定视图更容易.

Obviously the primary difference between my and Kent's point of view (as I understand it) is he reads ViewModel to be a Model of the View and I read it to be the thing that exposes the Model to the View. A subtle difference I'll admit, but I think the upshot is that I don't want to remove information that the model provides, even if it makes it easier for the specific view I'm using.

我的观点是基于这样一个假设:您应该能够交换视图,它们应该是稍纵即逝的东西,可能会根据屏幕尺寸、硬件、平台、延迟和环境的要求而改变.有趣的是,我从未真正需要这个功能,也没有看到任何曾经使用过它的东西(除了概念证明应用程序),但如果我们接受我们现在或将来不会使用它未来的任何时候,并且每个 ViewModel 都将与一个且只有一个 View 一起工作,那么我们不妨回到将所有代码放在代码隐藏文件中并将 ViewModel 完全扔掉 - 毕竟,它是如此紧密耦合,它也可能是同一个类.

My point of view is based on the assumption that you should be able to swap views out, they should be fleeting things that may change depending on the requirements of screen size, hardware, platform, latency and environment. The interesting twist is that I have never actually needed this functionality, nor seen anything (beyond proof of concept applications) that have ever used it, but if we accept that we won't use it now or at any point in the future, and that each ViewModel will work with one, and only one, View then we may as well go back to putting all the code in the code-behind file and throw the ViewModel out completely - after all, it's so tightly coupled that it may as well be the same class.

理想情况下,我希望 ViewModel 可以说这个值是一个整数,它永远是一个整数,你可以以任何你喜欢的方式显示它.但是你可以给我和我任何东西"我会尽力让它合身,如果我做不到,我会让你知道".基本上我的 MilesPerHour 属性应该有一个 int getter,但是一个对象 setter.这样,视图会保留我认为它们需要的所有信息,但不必担心转换或验证.

Ideally I would like a situation where the ViewModel can say "this value is an int, it will always be an int, and you can display it in anyway that you like. But you can give anything back to me and I'll do my best to make it fit, and if I can't I'll let you know". Basically my MilesPerHour property should have an int getter, but an object setter. That way the views keep all the information I feel they need, but don't have to worry about conversions or validation.

这篇关于MVVM ViewModel 是否应该执行类型转换/验证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆