將 DataContext 綁定到 ValidationRule
我有一個自定義 ValidationRule 需要訪問 ViewModel 以驗證提供的值以及 ViewModel 的其他屬性。我以前嘗試通過使用 ValidationGroup 來實現這一點,但放棄了這個想法,因為我正在修改的程式碼需要大量重構才能啟用這條路線。
我在新聞組上找到了一個執行緒,該執行緒顯示了一種將控制項的 DataContext 綁定的方法,其中 ValidationRule 通過從 DependencyObject 繼承的中間類執行到該 ValidationRule,但我無法將其綁定。
有人可以幫忙嗎?
我的 ValidationRule 如下…
class TotalQuantityValidator : CustomValidationRule { public TotalQuantityValidator() : base(@"The total number must be between 1 and 255.") { } public TotalQuantityValidatorContext Context { get; set; } public override ValidationResult Validate(object value, CultureInfo cultureInfo) { ValidationResult validationResult = ValidationResult.ValidResult; if (this.Context != null && this.Context.ViewModel != null) { int total = ... if (total <= 0 || total > 255) { validationResult = new ValidationResult(false, this.ErrorMessage); } } return validationResult; } }CustomValidationRule 定義如下…
public abstract class CustomValidationRule : ValidationRule { protected CustomValidationRule(string defaultErrorMessage) { this.ErrorMessage = defaultErrorMessage; } public string ErrorMessage { get; set; } }TotalQuantityValidatorContext 定義如下…
public class TotalQuantityValidatorContext : DependencyObject { public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(@"ViewModel", typeof(MyViewModel), typeof(TotalQuantityValidatorContext), new PropertyMetadata { DefaultValue = null, PropertyChangedCallback = new PropertyChangedCallback(TotalQuantityValidatorContext.ViewModelPropertyChanged) }); public MyViewModel ViewModel { get { return (MyViewModel)this.GetValue(TotalQuantityValidatorContext.ViewModelProperty); } set { this.SetValue(TotalQuantityValidatorContext.ViewModelProperty, value); } } private static void ViewModelPropertyChanged(DependencyObject element, DependencyPropertyChangedEventArgs args) { } }整個事情就是這樣使用的……
<UserControl x:Class="..." xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:val="clr-namespace:Validators" x:Name="myUserControl"> <TextBox Name="myTextBox"> <TextBox.Text> <Binding NotifyOnValidationError="True" Path="myViewModelProperty" UpdateSourceTrigger="PropertyChanged"> <Binding.ValidationRules> <val:TotalQuantityValidator> <val:TotalQuantityValidator.Context> <val:TotalQuantityValidatorContext ViewModel="{Binding ElementName=myUserControl, Path=DataContext}" /> </val:TotalQuantityValidator.Context> </val:TotalQuantityValidator> </Binding.ValidationRules> </Binding> </TextBox.Text> </TextBox> </UserControl>UserControl 的 DataContext 在程式碼隱藏中被設置為 MyViewModel 的一個實例。我知道此綁定的工作原理是標準控制項綁定按預期執行。
該
TotalQuantityValidator.Validate方法被正確呼叫,但每當我查看 的ViewModel屬性時Context,它始終為空( 的Context屬性被正確TotalQuantityValidator設置為 的實例TotalQuantityValidatorContext)。我可以從調試器中看到,永遠不會呼叫ViewModel屬性上的設置器。TotalQuantityValidatorContext任何人都可以建議我如何讓這個綁定工作嗎?
提前致謝。
我會避免使用驗證規則。如果您需要訪問 viewmodel 中的資訊來執行驗證,那麼最好將驗證邏輯放在 viewmodel 本身中。
您可以讓您的視圖模型實現
IDataErrorInfo,並簡單地在綁定上打開基於數據錯誤資訊的驗證。即使您沒有遇到需要上下文資訊的(非常常見的)問題,驗證規則也不是表達驗證的好方法:驗證規則通常與業務邏輯相關,或者至少與資訊的語義方面相關. Xaml 似乎是放置這些東西的錯誤位置 - 為什麼我要在源文件中放置一個業務規則,其主要工作是確定我的應用程序的佈局和視覺設計?
驗證邏輯屬於您的應用程序的更下方。甚至視圖模型也可能是錯誤的層,但在這種情況下,您可以簡單地讓視圖模型負責確定在哪裡找到驗證邏輯。