MVVM:仅当数据为VALID时,使绑定更新ViewModel

时间:2013-07-16 11:26:32

标签: wpf validation mvvm idataerrorinfo cinch

我有一个实现IDataErrorInfo接口的ViewModel。它只有一个属性:MyNumber。

在我看来有一个TextBox,用户可以在其中键入任何数字,但只有0到9的数字有效。

到目前为止,当验证失败时,文本框被标记为红色,但是我有一个问题:这不会避免设置ViewModel中的绑定属性。

简而言之,无论输入是否有效,都会设置MyNumber属性。我不希望MyNumber获取无效数据。

如何在纯MVVM方法中实现这一目标?

非常感谢!

2 个答案:

答案 0 :(得分:1)

我建议你以错误的方式解决这个问题。

如果您只想将输入限制为数字,请不要使用标准文本框。而是使用限制输入/格式有效的控件,例如WPF Control Toolkit中的IntegerUpDown / DecimalUpDown / DoubleUpDown - 可通过Nuget获得。然后,您可以将此控件的值绑定到视图模型中相应数字类型的字段。

答案 1 :(得分:0)

经过一段时间的研究,我得到了一个非常令人满意的解决方案:

由于我使用Cinch MVVM Framework by Sacha Barber,我的ViewModel中需要验证的属性使用一个非常方便的类,称为DataWrapper。它包装了实际属性并提供了一些有用的功能。事实上,我之前提到的MyProperty是一个DataWrapper。我在其“规则”集合中添加了所需的规则“x< = 5”。

DataWrapper类的一个非常好处是它包含一个名为“IsValid”的属性,它指示实际值是否违反了您为其设置的规则。

这封装了包装器中我需要检查验证的所有属性!

下一步是在XAML中设置绑定到DataWrapper,但是当DataWrapper包含VALID值时,我决定绑定仅适用

警告。前面的复杂解释。

你可以问我为什么需要这种行为。这有点复杂。视图就像一个向导,用户可以在其中选择模型的大小,颜色和其他图形方面。该模型在使用控件的视图中表示。为了简化理解(它比这更复杂),您可以假设模型一个名为Portrait 的类,它将在带有边框控件的视图中表示。用户输入Portrait的厚度的TextBox具有绑定到ViewModel(前面提到的DataWrapper)中的属性,我将称之为“BorderThicknessWrapper”。实际上,Binding设置为BorderThicknessWraper.DataValue,因此键入TextBox会修改DataWrapper中保存的数据的实际值。

这样,我们就可以获得用户在ViewModel中的TextBox中输入的值。

现在我们要制作代表模型的控件以反映更改。我们说我们将有一个Border作为Portrait的表示,所以每次更改BorderThicknessWrapper都会修改Border的边界强度。但是等等,我们希望它代表有效值,所以在XAML中我有这个!神奇的技巧;)

<Border>
  <Border.Style>
    <Style TargetType="{x:Type Border}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding BorderThickessWrapper.IsValid}" Value="True">
                <Setter Property="BorderThickness" Value="{Binding GutterWidth.DataValue}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Border.Style>

如您所见,Border有一个带有DataTrigger的Style,它指出“当包装器具有有效值时,设置绑定”。当属性无效时,将应用默认值。

到目前为止我们需要什么!

我希望你理解这个解决方案。这是基于纯MVVM的:D和漂亮的SOLID!