[英]MVVM: Make Binding update ViewModel only when data is VALID
我有一個實現IDataErrorInfo接口的ViewModel。 它只有一個屬性:MyNumber。
在我看來,有一個TextBox,用戶可以在其中輸入任何數字,但只有0到9之間的數字有效。
到目前為止,驗證失敗時,文本框將標記為紅色,但是我有一個問題:這無法避免在ViewModel中設置bound屬性。
簡而言之,無論輸入是否有效,都將設置MyNumber屬性。 我不希望MyNumber獲取無效數據。
如何以純MVVM方法實現這一目標?
非常感謝!
我建議您使用錯誤的方法。
如果您只想限制數字輸入,請不要使用標准的文本框。 而是使用一個限制輸入/格式有效的控件,例如WPF控件工具包中的IntegerUpDown / DecimalUpDown / DoubleUpDown-可通過Nuget獲得。 然后,您可以將此控件的值綁定到視圖模型中適當數字類型的字段。
經過一段時間的研究,我得出了一個非常令人滿意的解決方案:
由於我使用的是Sacha Barber的Cinch MVVM Framework ,因此ViewModel中需要驗證的屬性使用了一個非常方便的類,稱為DataWrapper。 它包裝了實際的屬性並提供了一些有用的功能。 實際上,我之前提到的MyProperty是一個DataWrapper。 我在其“規則”集合中添加了所需的規則“ x <= 5”。
關於DataWrapper類的一個很好的事情是,它包含一個名為“ IsValid”的屬性,該屬性指示實際值是否違反您為其設置的規則。
這會將所有需要檢查驗證的屬性封裝在包裝器中!
下一步是在XAML中設置到DataWrapper的綁定,但是我決定該綁定僅在DataWrapper包含VALID值時適用 。
警告。 前面有復雜的解釋。
您可以問我為什么需要這種行為。 這有點復雜。 該視圖就像一個向導,用戶可以在其中選擇模型的大小,顏色和其他圖形方面。 使用控件在視圖中表示模型。 為了簡化理解(比這稍微復雜一點),您可以假設模型是一個名為Portrait的類 ,它將在View中使用Border控件表示。 用戶在其中輸入Portrait的粗細的TextBox具有對ViewModel(前述的DataWrapper)中一個屬性的綁定,我將其稱為“ BorderThicknessWrapper”。 實際上,將Binding設置為BorderThicknessWraper.DataValue,因此在TextBox中鍵入內容會修改DataWrapper中保存的數據的實際值。
這樣,我們就擁有了用戶在ViewModel的TextBox中輸入的值。
現在,我們要制作代表模型的控件以反映更改。 我們說過,我們將以Border作為肖像的表示,因此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的樣式,該樣式指出“當包裝器具有有效值時,請設置綁定”。 當該屬性無效時,將應用默認值。
到目前為止我們需要什么!
希望您了解解決方案。 它是純基於MVVM的:D,而且非常堅固!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.