понедельник, 20 мая 2013 г.

Валідація у WPF використовуючи клас Validation та інтерфейс IDataErrorInfo.

Зміст

  1. Клас Validation.

  2. Валідація використовуючи IDataErrorInfo.


  1. Клас Validation.

У WPF є статичний клас Validation. Він надає методи і аттачед проперті, які підримують валідацію даних. Його статичні аттачед проперті ( static dependency properties) можна застосувати до будь-якого контролу.
Одні з найбільш важливих членів класу:
Errors повертає колекцію всіх активних ValidationError об 'єктів у зв'язаному елементі, тобто містить перелік повідомлень про помилки, які застосовуються при байдінгу до цього контролу.
HasError вказує, чи є які-небудь помилки в Errors проперті.
ErrorTemplate у випадку, якщо є помилка - дозволяє застосувати ControlTemplate.
По дефолту, Validation клас використовує ErrorTemplate, який надає червоний бордер навколо контролу.
Приклад:

2. Валідація використовуючи IDataErrorInfo.

Step 1. Створення моделі і реалізація інтерфейса IDataErrorInfo.
   1: class Person : INotifyPropertyChanged, IDataErrorInfo

   2:     {

   3:         #region Fields

   4:  

   5:         private int age;

   6:         private string name;

   7:         private string surname;

   8:  

   9:         #endregion

  10:         

  11:         #region Properties

  12:         

  13:         public int Age

  14:         {

  15:             get { return age; }

  16:             set { age = value; OnPropertyChanged("Age"); }

  17:         }

  18:         public string Name

  19:         {

  20:             get { return name; }

  21:             set { name = value; OnPropertyChanged("Name"); }

  22:         }

  23:         public string Surname

  24:         {

  25:             get { return surname; }

  26:             set { surname = value; OnPropertyChanged("Surname"); }

  27:         }

  28:  

  29:         #endregion

  30:  

  31:         #region INotifyPropertyChanged Members

  32:  

  33:         public event PropertyChangedEventHandler PropertyChanged;

  34:         private void OnPropertyChanged(String propertyName)

  35:         {

  36:             if (PropertyChanged != null)

  37:             {

  38:                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

  39:             }

  40:         }

  41:  

  42:         #endregion

  43:  

  44:         #region IDataErrorInfo Members

  45:  

  46:         public string Error

  47:         {

  48:             get { return String.Empty; }

  49:         }

  50:  

  51:         public string this[string columnName]

  52:         {

  53:             get

  54:             {

  55:                 string errorMessage = null;

  56:                 switch (columnName)

  57:                 {

  58:                     case "Name":

  59:                         if (String.IsNullOrEmpty(Name))

  60:                         {

  61:                             errorMessage = "Name is required";

  62:                         }

  63:                         else if (!(Name.Length > 1))

  64:                         {

  65:                             errorMessage = "Name must be at least 2 characters long";

  66:                         }

  67:  

  68:                         break;

  69:  

  70:                     case "Surname":

  71:  

  72:                         if (String.IsNullOrEmpty(Surname))

  73:                         {

  74:                             errorMessage = "Name is required";

  75:                         }

  76:                         else if (!(Surname.Length > 1))

  77:                         {

  78:                             errorMessage = "Surname must be at least 2 characters long";

  79:                         }

  80:                         break;

  81:  

  82:                     case "Age":

  83:                     

  84:                         if (Age <= 0)

  85:                         {

  86:                             errorMessage = "Age must be more than 0";

  87:                         }

  88:                         break;

  89:                 }

  90:                 return errorMessage;

  91:             }

  92:         }

  93:  

  94:         #endregion

  95:     }

Інтерфейс IDataErrorInfo забезпечує функціональні можливості представлення відомостей про помилки, які можуть бути пов'язані з користувацьким інтерфейсом. Тобто надає стандартний спосіб передачі інформації про помилки між моделлю і вюшкою.

Представляє наступні члени.:








ErrorПовертає повідомлення про помилку, яке показує причину відмовлення для даного обєкту.
ItemПовертає повідомлення про помилку для проперті з заданим іменем.

Приклад реалізації інтерфейса IDataErrorInfo


   1: #region IDataErrorInfo Members

   2:  

   3:        public string Error

   4:        {

   5:            get { return String.Empty; }

   6:        }

   7:  

   8:        public string this[string columnName]

   9:        {

  10:            get

  11:            {

  12:                string errorMessage = null;

  13:                switch (columnName)

  14:                {

  15:                    case "Name":

  16:                        if (String.IsNullOrEmpty(Name))

  17:                        {

  18:                            errorMessage = "Name is required";

  19:                        }

  20:                        else if (!(Name.Length > 1))

  21:                        {

  22:                            errorMessage = "Name must be at least 2 characters long";

  23:                        }

  24:  

  25:                        break;

  26:  

  27:                    case "Surname":

  28:  

  29:                        if (String.IsNullOrEmpty(Surname))

  30:                        {

  31:                            errorMessage = "Surname is required";

  32:                        }

  33:                        else if (!(Surname.Length > 1))

  34:                        {

  35:                            errorMessage = "Surname must be at least 2 characters long";

  36:                        }

  37:                        break;

  38:  

  39:                    case "Age":

  40:                    

  41:                        if (Age <= 0)

  42:                        {

  43:                            errorMessage = "Age must be more than 0";

  44:                        }

  45:                        break;

  46:                }

  47:                return errorMessage;

  48:            }

  49:        }

  50:  

  51:        #endregion

Step 2: Настройка байдінгу


На прикладі показано байдінг депенденсі проперті Text контролу TextBox на пропертю Name з ViewModelі.


   1: <TextBox  Name="NameTextBox" Text="{Binding Name, ValidatesOnDataErrors=True}" ></TextBox>

WPF апплікації володіють встроєною підтримкою IDataErrorInfo,все що для цього потрібно це встановити ValidatesOnDataErrors=True при байдінгу даних. Це дає можливість комунікувати з будь-якими типами даних, які реалізують інтерфейс IDataErrorInfo.
Step 3: Настройка ErrorTemplate
По дефолту, WPF повідомляє юзера про помилку підсвічуючи поле введеня даних червоним бордером.
Проте є можливість налаштувати вигляд контролу при наявності помилки, шляхом визначення нового стилю для ErrorTemplate текстбокса.
В наведеному прикладі показано , у випадку помилки, застосування нового Control Template для текстбоксу і ToolTip , який буде показувати месседж помилки.


   1: <Style TargetType="{x:Type TextBox}">

   2:         <Style.Triggers>

   3:             <Trigger Property="Validation.HasError" Value="true">

   4:                 <Trigger.Setters>

   5:                  

   6:                    <Setter Property="ToolTip"

   7:                         Value="{Binding RelativeSource={RelativeSource Self},

   8:                     Path=(Validation.Errors)[0].ErrorContent}"









/>
   9:                     

  10:                     <Setter Property="Validation.ErrorTemplate">

  11:                         <Setter.Value>

  12:                             <ControlTemplate>

  13:                                 <DockPanel LastChildFill="True" >

  14:                                     <Image  DockPanel.Dock="Right" Source="/Shared/BinaryResources/Images/error.png" Width="25" Height="25"

  15:                                             ToolTip="{Binding ElementName=MyAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" ></Image>

  16:                                     <Border BorderBrush="Red" BorderThickness="3">

  17:                                         <AdornedElementPlaceholder Name="MyAdorner" />

  18:                                     </Border>

  19:                                 </DockPanel>

  20:                             </ControlTemplate>

  21:                         </Setter.Value>

  22:                     </Setter>

  23:                     

  24:                 </Trigger.Setters>

  25:             </Trigger>

  26:         </Style.Triggers>

  27:     </Style>

Step 4: Хендлення події Error .

Validation.Error - рейзається коли у пов'язаному елементі виникає помилка, і при байдінгу вказано NotifyOnValidationError = True.








Routing strategyBubbling
DelegateRoutedEventHandler


Для хендлення події Error :


  • Встановити при байдінгу NotifyOnValidationError = True;
  • Встановити хендлер для події (Наприклад: Validation.Error = "TextBox_Error");


<TextBox Name="AgeTextBox" Text="{Binding Age, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" Validation.Error="TextBox_Error"></TextBox>


  • написати логіку в хендлері;


   1: private void TextBox_Error(object sender, ValidationErrorEventArgs e)

   2: {

   3:     System.Console.Beep();

   4:  

   5:     if (e.Action == ValidationErrorEventAction.Added)

   6:     {

   7:         MessageBox.Show(e.Error.ErrorContent.ToString());

   8:     }

   9:     else

  10:         System.Diagnostics.Trace.WriteLine("Validation error cleared");

  11:  

  12: }




Ось такий буде результат:

sample

Скачати приклад

Комментариев нет:

Отправить комментарий