我有一个实现IDataErrorInfo接口的ViewModel。它只有一个属性:MyNumber。
在我看来有一个TextBox,用户可以在其中键入任何数字,但只有0到9的数字有效。
到目前为止,当验证失败时,文本框被标记为红色,但是我有一个问题:这不会避免设置ViewModel中的绑定属性。
简而言之,无论输入是否有效,都会设置MyNumber属性。我不希望MyNumber获取无效数据。
如何在纯MVVM方法中实现这一目标?
非常感谢!
答案 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!