Сьогодні я покажу вам як легко можна валідувати дані введені користувачем. Для цього ми створимо простенький клас і поексперементуємо з ним. Першим буде розглянуто метод валідаціі на основі ексепшинів, після чого ми перейдемо до валідаціі яка появилась починаючи з фреймворка 3,5, валідаціі на основі IDataErrorInfo. Я пропущу створення проекту так як це вже було описано в попередніх постах і перейду безпосередньо до опису методу та реалізації.
Валідація на основі Exceptions.
Цей метод передбачає, що дані для користувацького інтерфейсу беруться з властивостей певного обєкту і відповідно коли вони змінюються на формі, вони автоматично записуюються в властивість обєкта, а так як записати в властивість типу int можна лише значення int то після того як користувач ввів щось типу “Десять” виникає помилка що дані не можуть бути записані і це відобразиться на нашому інтерфейсі. Такий же метод валідації існує в ASP NET. маю надію розглянути його роботу і там. Описав ніби правильно але в такому разі легше показати на прикладі:
Window1.xaml:
<Window x:Class="WpfValidation.Window1"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Window1" Height="300" Width="400"><Grid><Grid.RowDefinitions><RowDefinition Height="35" ></RowDefinition><RowDefinition Height="35" ></RowDefinition><RowDefinition Height="35" ></RowDefinition></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="50"></ColumnDefinition><ColumnDefinition></ColumnDefinition></Grid.ColumnDefinitions><TextBlock Grid.Row="0" Grid.Column="0" Margin="5">Name:</TextBlock><TextBlock Grid.Row="1" Grid.Column="0" Margin="5">Age:</TextBlock><TextBlock Grid.Row="2" Grid.Column="0" Margin="5">Sex:</TextBlock><TextBox Name="name" Grid.Row="0" Grid.Column="1" Width="200" Margin="5" Text="{Binding Path=Name, ValidatesOnExceptions=true, NotifyOnValidationError=true}"></TextBox><TextBox Name="age" Grid.Row="1" Grid.Column="1" Width="200" Margin="5" Text="{Binding Path=Age, ValidatesOnExceptions=true, NotifyOnValidationError=true}"></TextBox><TextBox Name="sex" Grid.Row="2" Grid.Column="1" Width="200" Margin="5" Text="{Binding Path=Sex, ValidatesOnExceptions=true, NotifyOnValidationError=true}"></TextBox></Grid></Window>
В редакторі це виглядатиме наступним чином:
Window1.xaml.cs:
using System.Windows;
namespace WpfValidation
{/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window{public Window1()
{InitializeComponent();loadData();}private void loadData(){UserItem item = new UserItem{
Name = "Ihor",
Age = 24,Sex = UserItem.SexEnum.Male};name.DataContext = item;age.DataContext = item;sex.DataContext = item;}}internal class UserItem{internal enum SexEnum{Male,Famale}public string Name { get; set; }public int Age { get; set; }public SexEnum Sex { get; set; }}}
Підсвітка спрацьовує автоматично при зміні фокусу, але якщо ми добавимо до стрічки з біндінгом наступний фрагмент “UpdateSourceTrigger=PropertyChanged“ то дані валідуватимуться зразу при введенні. Остаточний код xaml файлу наступний:
<Window x:Class="WpfValidation.Window1"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Window1" Height="300" Width="400"><Grid><Grid.RowDefinitions><RowDefinition Height="35" ></RowDefinition><RowDefinition Height="35" ></RowDefinition><RowDefinition Height="35" ></RowDefinition></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="50"></ColumnDefinition><ColumnDefinition></ColumnDefinition></Grid.ColumnDefinitions><TextBlock Grid.Row="0" Grid.Column="0" Margin="5">Name:</TextBlock><TextBlock Grid.Row="1" Grid.Column="0" Margin="5">Age:</TextBlock><TextBlock Grid.Row="2" Grid.Column="0" Margin="5">Sex:</TextBlock><TextBox Name="name" Grid.Row="0" Grid.Column="1" Width="200" Margin="5" Text="{Binding Path=Name, ValidatesOnExceptions=true, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged}"></TextBox><TextBox Name="age" Grid.Row="1" Grid.Column="1" Width="200" Margin="5" Text="{Binding Path=Age, ValidatesOnExceptions=true, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged}"></TextBox><TextBox Name="sex" Grid.Row="2" Grid.Column="1" Width="200" Margin="5" Text="{Binding Path=Sex, ValidatesOnExceptions=true, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged}"></TextBox></Grid></Window>
Тепер про використані властивості з біндінгом
UpdateSourceTrigger=PropertyChanged | Вказує коли саме проводити валідацію. Детальніше тут http://msdn.microsoft.com/ru-ru/library/system.windows.data.binding.updatesourcetrigger.aspx |
ValidatesOnExceptions | В даному випадку є основним і вказує чи робити валідацію данних при ексепшинах. |
NotifyOnValidationError | Вказує на необхідність інформування при виникненні помилок при валідацї. |
На цьому перший крок у валідації даних я вважаю завершеним, тепер ми переходимо до розгляду методу на основі IDataErrorInfo.
Валидация з використанням інтерфейсу IDataErrorInfo
Для реалізації даного методу нам необхідно реалізувати цей інтерфейс в нашому класі, він складається з індексатора і властивості. Властивість повертає стрічку з помилкою для всього класу а індексатор вказує на конкретну властивість в якій виникла помилка валідації, якщо помилок немає то відповідно повертається null. Виглядає цей інтерфейс наступним чином :
public interface IDataErrorInfo{string Error { get; }string this[string propertyName] { get; }}
Давайте попробуємо реалізувати цей інтерфейс на нашому прикладі:
public class UserItem : IDataErrorInfo{public enum SexEnum{Male,Famale}public string Name { get; set; }public int Age { get; set; }public SexEnum Sex { get; set; }public string this[string columnName]{get
{string msg = null;switch (columnName)
{case "Name":if (string.IsNullOrEmpty(this.Name))msg = "Name can't be empty.";
break;
case "Age":if (this.Age <= 0)msg = "Age can't be less then 0.";
break;
case "Sex":if (this.Sex != SexEnum.Famale && this.Sex != SexEnum.Male){msg = "Incorect Sex.";
}break;
default:
throw new ArgumentException("Unrecognized property: " + columnName);
}return msg;
}}public string Error{get
{return null;}}}
В даному випадку ми використали індексатор, але нічого не мішає нам використати властивість Error. Після запуску проекту ви побачите що ніякої валідації не відбувається і це не дивно тому що наш хамл поки що не знає про можливість валідації даних, тому добавимо до нього властивості які дозволять використовувати валідацію:
<Window x:Class="ValidationApp.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow" Height="350" Width="525"><Grid><Grid.RowDefinitions><RowDefinition Height="35" ></RowDefinition><RowDefinition Height="35" ></RowDefinition><RowDefinition Height="35" ></RowDefinition></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="50"></ColumnDefinition><ColumnDefinition></ColumnDefinition></Grid.ColumnDefinitions><TextBlock Grid.Row="0" Grid.Column="0" Margin="5">Name:</TextBlock><TextBlock Grid.Row="1" Grid.Column="0" Margin="5">Age:</TextBlock><TextBlock Grid.Row="2" Grid.Column="0" Margin="5">Sex:</TextBlock><TextBox Name="name" Grid.Row="0" Grid.Column="1" Width="200" Margin="5" Text="{Binding Path=Name, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"></TextBox><TextBox Name="age" Grid.Row="1" Grid.Column="1" Width="200" Margin="5" Text="{Binding Path=Age, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"></TextBox><TextBox Name="sex" Grid.Row="2" Grid.Column="1" Width="200" Margin="5" Text="{Binding Path=Sex, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"></TextBox></Grid></Window>
Я добавив наступні властивості :
- ValidatesOnDataErrors=True
- UpdateSourceTrigger=PropertyChanged
Перша для того щоб використати нашу валідацію, а друга для визначення часу її спрацьовування, в даному випадку після зміни тексту. Детальніше про ці та інші параметри на сайті майкрософта: http://msdn.microsoft.com/en-us/library/system.windows.data.binding.updatesourcetrigger.aspx
На остаток хотів би показати як можна програмно встановити контрол в стан помилки валідації, це може допомогти вам коли ви будете розробляти свою систему валідації (хоча я рекомендую використовувати стандартні методи так як в більшості випадків їх можливостей вистачає з головою). Для цього нам будуть потрібні два методи
- Validation.MarkInvalid
- Validation.ClearInvalid
Для включення стану помилки валідації:
Validation.MarkInvalid(name.GetBindingExpression(TextBox.TextProperty),new ValidationError(new ExceptionValidationRule(),name.GetBindingExpression(TextBox.TextProperty)));
Для очищення:
Validation.ClearInvalid(name.GetBindingExpression(TextBox.TextProperty));
Ці методи дозволять вам підсвітити валідацію на контролах відповідно до встановленого вами шаблону або шаблону заданого по замовчуванню.
Всім поменше помилок.
No comments:
Post a Comment