2010-10-18 20 views
5

Uygulamamda, TextBoxes'a bağlı sayısal (çift veya int) ViewModel özelliklerine sahibim. ViewModel, girilen değerlerin 'iş mantığı' için kabul edilebilir aralıklar içine düşüp düşmediğini kontrol etmek için IDataErrorInfo kullanır (örn. Yükseklik, negatif bir değer olamaz). Sayfa başına bir dizi TextBox'um var ve bir düğme (bir sihirbazda 'next' düşünün) özelliği etkinleştirildi. Bu özellik, bir bütün olarak sayfada herhangi bir hata olup olmadığını belirten bir ViewModel boolean'ına bağlı. Düğme etkinleştirme/devre dışı bırakma durumu, yazdığım IDataErrorInfo kurallarına göre geçerli/geçersiz değerler ile doğru şekilde güncelleştirildi. Ancak, bir giriş değeri dönüştürülmediğinden (yani "12bd39" geçerli bir ikili olmadığından) ve istisnai durumlar dışında benim durumumdan bir istisna çıktığında viewmodel'imi bilmeme izin vermenin bir yolu yoktur. 'next' düğmesi kötü girişe rağmen etkin kalacaktır. Ben görünümü sağlayabilirsiniz nasılViewModel ValidatesOnExceptions giriş hataları hakkında bilgi

<TextBox Text="{Binding Temperature, Mode=TwoWay, ValidatesOnExceptions=True, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"/> 

bir 'ValidatesOnExceptions' tarzı hatası oluştu biliyoruz: GUI ancak düzgün çünkü benim bağlayıcı bir Adorner hatayı yansıtır. Josh Smith'in aldığı here, her ViewModel özelliğini bir dize haline getirmeye ve çok fazla iş gibi görünen kendi istisna kontrolünüzü yuvarlamaya dayanıyor gibi görünüyor. Ben ayrıca Karl Shifflett uygulamasına here içine bakarak başladı, ama ben görünümün codebehind dosyasına bu kodu koyarak ne zaman beklenebilir yönlendirilir olayı yakalamak gibi olamaz:

public ViewClass() 
{ 
this.InitializeComponent(); 
     this.AddHandler(System.Windows.Controls.Validation.ErrorEvent, new RoutedEventHandler(ValidationErrorHandler)); 
} 

private void ValidationErrorHandler(object sender, RoutedEventArgs e) 
{ 
    var blah = e as System.Windows.Controls.ValidationErrorEventArgs; 
    if (blah.Action == ValidationErrorEventAction.Added) 
    { 
    } 
    else if (blah.Action == ValidationErrorEventAction.Removed) 
    {  
    } 
} 

Silverlight siz de abone olabilirsiniz bir olay gibi görünüyor ancak WPF'de tam eş değeri bulamıyorum (3.5). Herhangi bir yardım takdir edilir!

+0

Belki bu alternatif yaklaşım sizin için çalışacaktır: http://stackoverflow.com/questions/921601/how-can-i-handle-a-validation-error-in-my-viewmodel-instead-of-my- views-code-beh – Ragepotato

+0

Yönlendirilen olayları görüntüleme modelinize bağlamak ve arkasındaki kodu önlemek için Josh Smith'in çözümünü önermek asla iyi bir fikir değildir. IDataErrorInfo arabirimi, işleri "temiz" tutmak istiyorsanız gidilecek yoldur. –

+0

Katılıyorum. Sıfırdan yeni bir proje başlatırken kesinlikle Josh Smith'in çözümüne gideceğim. Ne yazık ki bu durumda bunu yapmak, çok dar bir zaman diliminde 30 görüş modelini yeniden gözden geçirmemi gerektirecektir. – astonish

cevap

3

Ben Validation.ErrorEvent abone View için bir temel sınıf olay

public class MVVMViewBase : UserControl 
    { 
     private RoutedEventHandler _errorEventRoutedEventHandler; 
     public MVVMViewBase() 
     { 
      Loaded += (s, e) => 
       { 
        _errorEventRoutedEventHandler = new RoutedEventHandler(ExceptionValidationErrorHandler); 
        AddHandler(Validation.ErrorEvent, _errorEventRoutedEventHandler); 
       }; 

      Unloaded += (s, e) => 
       { 
        if (_errorEventRoutedEventHandler != null) 
        { 
         RemoveHandler(Validation.ErrorEvent, _errorEventRoutedEventHandler); 
         _errorEventRoutedEventHandler = null; 
        } 
       }; 
     } 

     private void ExceptionValidationErrorHandler(object sender, RoutedEventArgs e) 
     { 
      ValidationErrorEventArgs args = (ValidationErrorEventArgs) e; 
      if (!(args.Error.RuleInError is IUiValidation)) return; 

      DataErrorInfoViewModelBase viewModelBase = DataContext as DataErrorInfoViewModelBase; 
      if(viewModelBase == null) return; 

      BindingExpression bindingExpression = (BindingExpression) args.Error.BindingInError; 
      string dataItemName = bindingExpression.DataItem.ToString(); 
      string propertyName = bindingExpression.ParentBinding.Path.Path; 

      e.Handled = true; 
      if(args.Action == ValidationErrorEventAction.Removed) 
      { 
       viewModelBase.RemoveUIValidationError(new UiValidationError(dataItemName, propertyName, null)); 
       return; 
      } 

      string validationErrorText = string.Empty; 
      foreach(ValidationError validationError in Validation.GetErrors((DependencyObject) args.OriginalSource)) 
      { 
       if (validationError.RuleInError is IUiValidation) 
       { 
        validationErrorText = validationError.ErrorContent.ToString(); 
       } 
      } 
      viewModelBase.AddUIValidationError(new UiValidationError(dataItemName, propertyName, validationErrorText)); 
     } 
    } 

ve AddUIValidationError ve RemoveUIValidationError

bütün Ayrıca

bilgilendirilir ViewModel = DataErrorInfoViewModelBase için bir temel sınıf yönlendirilir var ValidationRule sınıflarım, yalnızca UI hata yayılımının (üyeler) bir parçası olarak sınıfı işaretlemek için kullanılan IUiValidation uygular. (Aynı amaçla bir öznitelik kullanabilirsiniz).

İlgili konular