我们刚刚进入MVVM在WPF。
我们已经实现了我们的ViewModels与我们的观点结合“强类型的属性(INT,双?等)。
类型转换工作确定居多,所以输入数据是很简单的。 但是,我们遇到与验证问题。
比如说,如果一个非数字的值被绑定到一个数值属性文本框中输入,转换失败,该属性从未设置的,我们从来没有得到一个机会,提供适当的反馈给用户。 更糟的是,该属性保留其当前值,导致什么在视图中显示,什么实际上是在视图模型之间的不匹配。
这一切都可以用价值转换器来处理,我知道了。 但我所看到的若干意见到转换不应该是观点的责任,在所有的效果。 什么在视图中输入是字符串,转换,验证等应在ViewModel负责(所以按照这种说法)。
如果是这样,我们应该重写大部分我们的ViewModels属性的字符串,并通过接口的IErrorInfo提供错误的信息,例如。 这必将使在视图更简单,更瘦XAML。 在另一方面,转换,验证等会少一些声明,明确和灵活,从视图设计的点。
在我们看来,这两种方法是根本不同的,所以我们决定之前,我们想对此事也有知情SO意见。
所以:应该的ViewModels暴露的简化,“基于文本的”接口视图和内部处理转换? 还是应该视图模型属性公开的实际数据类型,这样留下来的家务的观点来处理?
更新:
很难挑选一个赢家,但我终于降落在一个你谁的结论或多或少像我这样的。
具体来说,我们决定保留键入的视图模型属性。 造成这种情况的主要原因是它使我们在视图的设计灵活性,并在XAML明确,声明转换/格式的能力。
我注意到你的假设,谁将会在这个我们不同意,该视图的设计是固定的,并且准备好了。 因此,没有关于转换的决定,格式化等需要在视图中进行。 但我们是一个敏捷的过程,我们还没有拿到所有的UI的细节问题详细想通了就提前。
事实上,离开UI的细节,制定出沿途留下的创作空间,此外,在我看来,即使是精心制定设计总是会结束整个实施过程中变形。
所有这一切的一点是,而业务规则执行的视图模型肯定属于,它在我们看来,简单的转换和格式是一个视图的事情。 也许这听起来像是异端邪说,但我并不真的认为在视图类型转换需要在所有的(只要AV我们单元测试的实际类型转换器)单元测试。
所有的一切的大讨论,伙计们,精心拟定,知情意见。 谢谢。
这是一个非常有趣的问题,另一个我不觉得有一个明确的答案,但我会尽我所能,把我的想法在那里。
看着我的理解MVVM模式,视图模型的关键是要在某种程度上视图没有关于视图将使用它的方式做任何假设可以理解公开数据。 举一个例子,让我们假设我们正在建模一辆汽车的速度:
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,因为这是它在模型中。 这样做的缺点你已经在你的问题中,但主要优势是它给视图的创建者的信息,有关如何显示数据的宝贵作品。 请记住,我们(作为视图模型的作者),不知道是什么的视图样子。 通过承诺数据是一个int视图可使用文本框或其他一些控制只接受数字(拨号,例如)来显示信息的想法。 如果说,我们要的方式,我们假设数据格式是有帮助的查看它需要的是重要的权力远离它。
在另一方面,我们在现实世界中的工作。 我们往往知道的观点是什么。 我们很少即插即用同一视图模型的顶部,并加入转换代码到视图模型不同的看法简直是容易得多。 我不认为这是正确的,但是,这并不意味着使用它,你不会找到我的生产代码...
最后(我敢肯定,你知道这一点,但对于完井的缘故...)业务逻辑应该在视图模型来完成。 如果我们认为汽车不应该去上面70英里每小时那么它是不执行该视图的责任。 所以,你仍然会结束了某种错误提供商,但在业务,而不是显示级别。
好吧,也许这不是最终....
我想,以解决肯特提出的意见和我的想法不适合评论。
显然,我和观点肯特的点之间的主要区别(据我所知)是他读的ViewModel要查看的模式,我看它是暴露模型视图的东西。 一个微妙的差异我承认,但我认为结果是,我不希望删除的信息,该模型提供,即使它更容易为我使用的特定视图。
我的观点是基于这样的假设,你应该能够交换意见时,他们应该是可以根据屏幕尺寸,硬件,平台,延迟和环境的要求改变转瞬即逝的东西。 有趣的转折是,我从来没有真正需要这个功能,也没有看到任何(超越的概念应用证明)已经使用过它,但如果我们承认,我们现在不使用它,或者在未来的任何位置,每个视图模型将与一个,只有一个工作,查看那么我们不妨回去把所有的代码,在代码隐藏文件,并抛出视图模型进行彻底的 - 毕竟,它是如此紧密结合的,它可能还有是同一类。
我非常希望的情况下视图模型可以说“这个值是一个int,它永远是一个int,你可以以任何你喜欢的显示出来。不过你可以对我付出一切回来,我会尽我最好使之适合,如果我不能,我会让你知道。” 基本上我MilesPerHour属性应该有一个int消气,而是一个物体设定。 这样的观点保持我觉得他们需要的所有信息,而不必担心转换或验证。
当然它属于视图模型,对于所有的通常的原因,其中包括:
- 设计师拥有XAML。 你想设计人员必须理解和执行必要的类型转换和验证逻辑?
- 可测性。 难道你想验证你的转换和验证逻辑是否正常工作? 如果它嵌入在视图中这是非常困难。
在另一方面,转换,验证等会少一些声明,明确和灵活,从视图设计点
我认为这是一个有争议的问题,因为该视图设计师要负责这些事情。 设计师正在努力使用户界面的外观和感觉某种方式; 它是谁实现业务逻辑,包括转换和验证逻辑的开发。
这是一个很好的问题,我肯定可以看到讨论的两侧。
我的想法是,你真正寻找的是一个正确的NumericInputControl
,你可以在你的XAML中使用。 这将提供更好的用户体验,因为用户将无法在数字字段意外输入文字,并且因为控制输入约束而不验证它,你可以保持更多的强类型视图模型。
我不知道你想怎么去实现一个,我知道,经典的旋转/的NumericUpDown控件失宠,因为它们不是触摸友好的,但我不相信,引进这种控制将违反设计方法或您的ViewModels的纯度。 您会收到通过一个号码,然后可以在适当的地方范围,验证,供应反馈IDataErrorInfo
像往常一样,等等。 :)这个技术可以让您获得两全其美的,没有任何真正的缺点(除了建立一个数字控制的)。
如若MVVM视图模型进行类型转换/验证?
是 。
视图模型是视图和模型之间的抽象层 - 的理想场所执行任何类型的转换(而不是麻烦的值转换器)。 验证绝对应该发生的视图模型的一部分。
我们用我们的视图模型来处理尽可能多的数据类型转换。 这减少了值转换器到一些非常特殊的情况下需要。 要公开什么类型是最简单的一种观点消耗。 这一直运作良好。
你提出的一个具体问题:
比如说,如果一个非数字的值被绑定到一个数值属性文本框中输入,转换失败,该属性从未设置的,我们从来没有得到一个机会,提供适当的反馈给用户。 更糟的是,该属性保留其当前值,导致什么在视图中显示,什么实际上是在视图模型之间的不匹配。
可能通过暴露您的视图模型类型可空类型来处理。 这应该仍然允许底层源进行更新,即使输入无效数据,并触发验证。 这曾在类似的情况下,我们曾与DateTime和日期时间选择器。
保持视图当哑巴。 我们没有正式的设计师,我们的开发商是我们的设计师,所以保持视线哑有一些好处:
- 我们(开发商)去保持我们的理智(XAML稍差详细)
- 业务逻辑(包括验证)停留在视图模型和可以使测试
祝好运!
-Z
还是应该视图模型属性公开的实际数据类型,这样留下来的家务的观点来处理?
转换和模板中进行View
,因为他们都只是转换values
, models
和viewmodels
到controls
! Controls
里面只有可View
。
验证是做ViewModel
,因为验证是按照商业规则进行,甚至可以通过电话来完成远程服务。 查看一无所知的业务规则,但他知道如何呈现验证结果。
比如说,如果一个非数字的值被绑定到一个数值属性的文本框中输入
一个正确制作的数字文本框控件从未允许用户输入一个非数字的值。