2

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

在我看来,有一个文本框,用户可以在其中输入任何数字,但只有 0 到 9 之间的数字有效。

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

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

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

非常感谢!

4

2 回答 2

1

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

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

于 2013-07-17T08:46:49.667 回答
0

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

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

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

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

下一步是在 XAML 中为 DataWrapper 设置一个绑定,但我决定该绑定在 DataWrapper 包含 VALID 值时适用。

警告。前面有复杂的解释。

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

这样,我们就有了用户在 ViewModel 的 TextBox 中输入的值。

现在我们要制作代表模型的控件以反映更改。我们说过我们会有一个Border作为我们Portrait的表示,所以每次更改BorderThicknessWrapper都会修改Border的BorderThickness。但是等等,我们确实希望它代表有效值,所以在 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 并且非常可靠!

于 2013-07-17T07:12:28.993 回答