如何使ViewModel意识到转换错误

时间:2014-05-13 12:08:40

标签: wpf mvvm

我正在设计MVVM之后的WPF应用程序。我的ViewModel正在公开一个名为DoubleValue的Double属性,该属性绑定到TextBox中的View。我为绑定设置了“ValidatesOnDataErrors = True”。因此,如果用户键入无法转换为Double的字符串,则会显示红色背景。

在我的ViewModel我也有一个Command对象,让我们调用SaveCommand,其CanExecute委托取决于VM中是否有任何错误(我的ViewModelBase类实现IDataErrorInfo,我有一个可覆盖的ValidatePropertyByName函数,验证错误存储在字典中。)但现在我的问题是,如果我在TextBox中给出一个无效的字符串,由于转换失败,它从不调用绑定的setter适当的价值。换句话说,不调用ValidatePropertyByName,并且错误字典仍然是先前的状态,通常是干净的。因此,如果现在用户单击“保存”按钮(由于错误字典已清除而启用),则SaveCommand将使用先前的有效double值执行以进行保存。这显然不太好。

那么我怎样才能让ViewModel知道这些转换错误?

更新:

一些代码示例:

绑定属性是这样的:

Public Property DoubleValue As Double
        Get
            Return _doubleValue
        End Get
        Set(value As Double)
            If value <> _doubleValue Then
                _doubleValue = value
                RaisePropertyChanged("DoubleValue")
            End If
        End Set
    End Property
    Private _doubleValue As Double

我的绑定是这样的:

<TextBox Grid.Row="3" Text="{Binding DoubleValue, ValidatesOnDataErrors=True}" />

现在我的问题是:如果我在文本框中输入字符串“XXX”,因为它无法转换为double值,所以DoubleValue的setter永远不会被调用。因此,属性值仍然是之前的(有效)值。现在,如果我的SaveCommand被执行,它将使用此前一个有效值执行保存操作,这将使用户感到困惑。

2 个答案:

答案 0 :(得分:2)

最简单的方法是在viewmodel中使用字符串属性。然后,您将获得用户的所有输入,并可以在您的viewmodel中验证它。缺点是当你去模型时你必须将值转换为正确的类型。

如果您不想要这个,您必须创建自己的控件或更好的行为,以便使用可以只输入您的viewmodel期望的值。例如。 NumericInputBehavior。

答案 1 :(得分:1)

你不能简单地把这两件事放在一起。一个是ViewModel中的常规验证。另一个是特定于控制的问题,如不可转换的值。

因此,有两种方法可以解决这个问题:

1)不要使用转换器。只需绑定字符串。在ViewModel中,您可以使用验证来检查有效值。 (更多MVVM)

2)将ValidationErrors存储在控制端,并将它们与viewmodel错误合并。这并不容易,但是创建一个源来绑定UI中的所有问题的好方法。我们正在为复杂的文本框工作。这意味着控件中的手动代码,但对于复杂的自定义控件,这是可以的,我相信。

编辑:只是为了详细阐述第二点。我们在Control中有一个Type ObservableCollection的DependencyProperty。然后,您可以将此Collection绑定到ViewModel属性,并且只要您的控件在集合中移动Error,它就会在viewModel中可用。然后,您可以在验证实现中使用此集合。这适用于较大的控件。

Edit2:对于我在评论中提到的MarkInvalid Stuff。它看起来像这样:

DataErrorValidationRule validationRule = new DataErrorValidationRule();
ValidationError validationError = new ValidationError(validationRule, myTextBox.GetBindingExpression(TextBox.TextProperty)) { ErrorContent = "My custom message" };
Validation.MarkInvalid(myTextBox.GetBindingExpression(TextBox.TextProperty), validationError);

当您无法转换新的给定值或

时,您可以从TextChanged内部调用
Validation.ClearInvalid(myTextBox.GetBindingExpression(TextBox.TextProperty))

也许这会有所帮助?