2013-08-04 1 views
3

У меня есть приложение с многократными ViewModels. В некоторых свойствах есть DataAnnotations.Проверка данных в mvvm

[Required(ErrorMessage = "Field 'Range' is required.")] 
    [Range(1, 10, ErrorMessage = "Field 'Range' is out of range.")] 
    public int Password 
    { 
     get 
     { 
      return _password; 
     } 
     set 
     { 
      if (_password != value) 
      { 
       _password = value; 
       RaisePropertyChanged("Password"); 
      } 
     } 
    } 

Как проверка может быть сделано путем реализации интерфейса IDataErrorInfo или INotifyDataErrorInfo для всех ViewModels?

Я использую статью This, но проверяю, когда propertychange и не проверяют требуемое поле.

ответ

2

Вот простой пример, который использует IDataErrorInfo. Это должно помочь вам начать работу.

XAML: за

<Grid> 
    <Grid.Resources> 
     <ControlTemplate x:Key="LeftErrorTemplate"> 
      <StackPanel Orientation="Horizontal"> 
       <TextBlock Text="{Binding AdornedElement.(Validation.Errors).[0].ErrorContent, ElementName=ErrorAdorner}" Background="Red" Foreground="White" FontWeight="Bold" VerticalAlignment="Center"/> 
       <AdornedElementPlaceholder x:Name="ErrorAdorner"> 
        <Border BorderBrush="Red" BorderThickness="1" /> 
       </AdornedElementPlaceholder> 
      </StackPanel> 
     </ControlTemplate> 
    </Grid.Resources> 
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="158,66,0,0" Name="textBlock1" Text="Name" VerticalAlignment="Top" Width="44" /> 
    <TextBox Height="23" HorizontalAlignment="Left" Margin="217,65,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" 
      Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" 
      Validation.ErrorTemplate="{StaticResource LeftErrorTemplate}"/> 
</Grid> 

Код:

using System; 
using System.Windows; 
using System.ComponentModel; 

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      var vm = new ViewModel(); 

      this.DataContext = vm; 
     } 
    } 

    public class ViewModel : ObservableBase, IDataErrorInfo 
    { 
     private string _Name; 

     public string Name 
     { 
      get { return _Name; } 
      set 
      { 
       _Name = value; 
       OnPropertyChanged("Name"); 
      } 
     } 

     public string Error 
     { 
      get { throw new NotImplementedException(); } 
     } 

     public string this[string columnName] 
     { 
      get 
      { 
       string errorMessage = string.Empty; 

       switch (columnName) 
       { 
        case "Name": 
         if (string.IsNullOrEmpty(Name)) 
          errorMessage = "Enter name"; 
         else if (Name.Trim() == string.Empty) 
          errorMessage = "Enter valid name"; 
         break; 
       } 
       return errorMessage; 
      } 
     } 

    } 

    public class ObservableBase : INotifyPropertyChanged 
    { 

     public event PropertyChangedEventHandler PropertyChanged; 

     public void OnPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 
+0

Спасибо, но я хочу создать класс проверки для всего приложения и все ViewModel наследуют класс проверки. –

1

Привет вам придется создать какой-то метод, который проверяет аннотаций Like ValidateMethod в моем коде

public class ViewModel:INotifyPropertyChanged,IDataErrorInfo 
    { 
     int _password; 

     [Required(ErrorMessage = "Field 'Range' is required.")] 
     [Range(1, 10, ErrorMessage = "Field 'Range' is out of range.")] 
     public int Password 
     { 
      get 
      { 
       return _password; 
      } 
      set 
      { 
       if (_password != value) 
       { 
        _password = value; 
        Validate("Password", value); 
        Notify("Password"); 
       } 
      } 
     } 

     private void Validate(string propertyName, object value) 
     { 
      if (string.IsNullOrEmpty(propertyName)) 
       throw new ArgumentNullException("propertyName"); 

      string error = string.Empty; 

      var results = new List<System.ComponentModel.DataAnnotations.ValidationResult>(2); 

      bool result = Validator.TryValidateProperty(
       value, 
       new ValidationContext(this, null, null) 
       { 
        MemberName = propertyName 
       }, 
       results); 

      if (!result && (value == null || ((value is int || value is long) && (int)value == 0) || (value is decimal && (decimal)value == 0))) 
       return; 

      if (!result) 
      { 
       System.ComponentModel.DataAnnotations.ValidationResult validationResult = results.First(); 
       if (!errorMessages.ContainsKey(propertyName)) 
        errorMessages.Add(propertyName, validationResult.ErrorMessage); 
      } 

      else if (errorMessages.ContainsKey(propertyName)) 
       errorMessages.Remove(propertyName); 
     } 

     #region INotifyPropertyChanged 

     public void Notify(string propName) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(propName)); 

     } 
     public event PropertyChangedEventHandler PropertyChanged; 

     #endregion 

     #region IDataErrorInfo 

     public string Error 
     { 
      get { throw new NotImplementedException(); } 
     } 

     private Dictionary<string, string> errorMessages = new Dictionary<string, string>(); 

     public string this[string columnName] 
     { 
      get 
      { 
       if(errorMessages.ContainsKey(columnName)) 
        return errorMessages[columnName]; 
       return null; 

      } 
     } 

     #endregion 
    } 

> XAML

<TextBox Text="{Binding Password, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" Height="70" Width="200" /> 

xaml.cs

public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = new ViewModel(); 
    } 

Вам нужно вызвать метод Validate из сеттеров имущества, которое применяется DataAnnotations и убедитесь, что называть его перед уведомлением PropertyChanged.

+0

Спасибо, но PropertyChanged не уведомляет в требуемой проверке, и я должен вызвать метод проверки для всего необходимого свойства в кнопке отправки. –

+0

Да Вам нужно будет позвонить, что для всех свойств, которые вы хотите выдать, и что вы подразумеваете под PropertyChanged, не уведомляя при необходимости проверку – ethicallogics

+0

, проверки выполняются только при выполнении привязки. Что происходит, когда пользователь запускает экран и нажимает кнопку отправки напрямую ... Никакое связывание не происходит, и, следовательно, проверка не выполняется. –