是",;“尼斯”;WPF的特性真的那么好吗?还是他们控制力太强?

是",;“尼斯”;WPF的特性真的那么好吗?还是他们控制力太强?,wpf,mvvm,Wpf,Mvvm,所以我是MVVM的新手,我一直在努力解决一些关于用户输入验证的问题。WPF有一些内置的功能,看起来像“魔术”,一般来说,我知道“魔术”并不好 例如:如果将文本框绑定到类型为double的属性,并且用户在该文本框中输入“hello”,则WPF会在文本框周围自动显示红色边框,通知用户输入无效 这一切都很好,但它确实像“魔法”。一位经验丰富的开发人员告诉我,WPF和类似的应用程序构建者希望拥有太多的控制权。他说,在web开发中,视图不知道该属性是什么类型。这对我来说很有意义。因此,这就引出了我的一般性

所以我是MVVM的新手,我一直在努力解决一些关于用户输入验证的问题。WPF有一些内置的功能,看起来像“魔术”,一般来说,我知道“魔术”并不好

例如:如果将
文本框
绑定到类型为
double
的属性,并且用户在该
文本框
中输入“hello”,则WPF会在
文本框
周围自动显示红色边框,通知用户输入无效

这一切都很好,但它确实像“魔法”。一位经验丰富的开发人员告诉我,WPF和类似的应用程序构建者希望拥有太多的控制权。他说,在web开发中,视图不知道该属性是什么类型。这对我来说很有意义。因此,这就引出了我的一般性问题-WPF视图是否应该理解属性类型?-如果我将属性类型声明为
字符串
,那么我就可以完全控制视图。而不必使用WPF的“智能”
TextBox
“魔力”

表达我的问题的另一种方式是-应该在模型或ViewModel中声明属性类型吗?

我理解,如果您在模型中将属性类型声明为
double
,在ViewModel中将属性类型声明为
string
,则必须在模型中对其进行解析。在我所看到的大多数MVVM应用程序示例中,整个应用程序的属性类型都是相似的,但我认为一个不了解它在使用什么的“哑”视图会更好

回到我的示例:如果属性被声明为
字符串
,则可以完全控制输入所需的格式,同时防止无效输入。这似乎是一个比信任WPF
文本框更好的解决方案

是的,它应该这样做

卡尔·希夫莱特有一篇关于它的文章

解决方案是检测无效输入。当用户输入无效的数据类型时,数据绑定管道将引发异常。当它发生时,在视图上处理它,然后在视图模型上添加错误消息,以便您可以在需要时使用它

默认情况下,WPF会吞咽该数据绑定异常,但您可以在视图中添加加载事件的处理程序

_errorEventRoutedEventHandler = new RoutedEventHandler(ExceptionValidationErrorHandler);
this.AddHandler(System.Windows.Controls.Validation.ErrorEvent, _errorEventRoutedEventHandler, true);
实现处理程序

private void ExceptionValidationErrorHandler(object sender, RoutedEventArgs e)
{
    // Add logic to handle this invalid data type exception. 
    // Add error messages to viewmodel, show notification dialog, etc
    ...
}
将XAML绑定NotifyOnValidationErrorValidatesOnDaErrorsValidatesOnceptions上的这些属性设置为true

Text="{Binding UnitPrice, StringFormat=c, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}"
就是这样。

是的,应该是这样

卡尔·希夫莱特有一篇关于它的文章

解决方案是检测无效输入。当用户输入无效的数据类型时,数据绑定管道将引发异常。当它发生时,在视图上处理它,然后在视图模型上添加错误消息,以便您可以在需要时使用它

默认情况下,WPF会吞咽该数据绑定异常,但您可以在视图中添加加载事件的处理程序

_errorEventRoutedEventHandler = new RoutedEventHandler(ExceptionValidationErrorHandler);
this.AddHandler(System.Windows.Controls.Validation.ErrorEvent, _errorEventRoutedEventHandler, true);
实现处理程序

private void ExceptionValidationErrorHandler(object sender, RoutedEventArgs e)
{
    // Add logic to handle this invalid data type exception. 
    // Add error messages to viewmodel, show notification dialog, etc
    ...
}
将XAML绑定NotifyOnValidationErrorValidatesOnDaErrorsValidatesOnceptions上的这些属性设置为true

Text="{Binding UnitPrice, StringFormat=c, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}"

就是这样。

因为您使用的是强类型语言,所以迟早需要验证。我不确定如果不使用已经在手的验证形式,您希望实现什么。不要忘记,当给出无效输入时,您可以修改视图以执行任何您想要的操作。如果您不希望抛出任何异常(如@Rachel所解释的),那么使用string属性可能会阻止它们

声明

连接到数据库的属性在模型中声明。将模型转换为用户友好的特性需要在ViewModel中声明。例如,我们有一个存储在数据库中的值(valueA)。valueA使用用户可用的两个输入字段(valueB和valueC)进行计算。在本例中,valueA在模型中声明,但valueB和valueC仅在ViewModel中声明,因为它们不需要存储在数据库中。(从技术上讲,这三个选项在ViewModel中都可用,但在模型中仅声明valueA)

我的理解是:

  • 模型具有存储在数据库中的属性
  • ViewModel将模型转换为用户可以处理的内容(反之亦然)
  • 视图或多或少是“ViewModel的输入区域”,在该区域中,用户可以使用图形进行辅助

由于您使用的是强类型语言,您迟早需要验证。我不确定如果不使用已经在手的验证形式,您希望实现什么。不要忘记,当给出无效输入时,您可以修改视图以执行任何您想要的操作。如果您不希望抛出任何异常(如@Rachel所解释的),那么使用string属性可能会阻止它们

声明

连接到数据库的属性在模型中声明。将模型转换为用户友好的特性需要在ViewModel中声明。例如,我们有一个存储在数据库中的值(valueA)。valueA使用用户可用的两个输入字段(valueB和valueC)进行计算。在本例中,valueA在模型中声明,但valueB和valueC仅在ViewModel中声明,因为它们不需要存储在数据库中。(从技术上讲,这三个选项在ViewModel中都可用,但在模型中仅声明valueA)

我的理解是:

  • 模型具有存储在数据库中的属性
  • 视图模型<