Мы будем производить валидацию данных формы в автоматическом режиме, при помощи правил, описанных в декларативном стиле. Возьмем простейшую форму:
Здесь есть несколько обычных текстовых полей, поле ввода числа и поле для e-mail'a. Зададим следующие правила для нашей формы:
Поля Фамилия, Имя и Отчество должны быть заполнены как минимум одним печатным (не whitespace) символом:
txtSurname
.ValidateControl()
.IsNotNullOrWhitespace();
txtName
.ValidateControl()
.IsNotNullOrWhitespace();
txtMiddleName
.ValidateControl()
.IsNotNullOrWhitespace();
Возраст должен быть не менее 16 лет. Если указанный возраст менее 21 года – необходимо вывести предупреждение, но разрешить сохранить форму:
nmAge
.ValidateControl()
.IsTrue(ctl => ctl.Value >= 16, "Возраст должен быть не менее 16 лет.", ValidationType.Required)
.IsTrue(ctl => ctl.Value >= 21, "Некоторый контент (21+) для вас будет недоступен.", ValidationType.Optional);
Поле e-mail должно быть заполнено корректным значением (или по крайней мере похожим на e-mail):
txtEMail
.ValidateControl()
.IsValidEMail(false);
Если все поля заполнены правильно – разрешить нажатие кнопки «Сохранить», иначе – нет:
butSave
.ValidateControl()
.EnableByValidationResult();
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
// проверим, что текстовые поля заполнены
txtSurname
.ValidateControl()
.IsNotNullOrWhitespace();
txtName
.ValidateControl()
.IsNotNullOrWhitespace();
txtMiddleName
.ValidateControl()
.IsNotNullOrWhitespace();
// зададим жесткое ограничение в 16 лет
// и не жесткое ограничение (предупреждение не препятствующее вводу формы) в 21 год
nmAge
.ValidateControl()
.IsTrue(ctl => ctl.Value >= 16, "Возраст должен быть не менее 16 лет.", ValidationType.Required)
.IsTrue(ctl => ctl.Value >= 21, "Некоторый контент (21+) для вас будет недоступен.", ValidationType.Optional);
// включим проверку на ввод корректного e-mail'а в этом поле
txtEMail
.ValidateControl()
.IsValidEMail(false);
// по результатам валидации будем разрешать/запрещать указанную кнопку
butSave
.ValidateControl()
.EnableByValidationResult();
}
}
Что мы получим при запуске формы? Во первых: мы получим удобное подсвечивание каждого поля, значение которого заполнено некорректными данными. Во вторых: если подвести курсор мыши к индикатору мы увидим что именно хочет от нас форма:
В третьих: кнопка «Сохранить» будет доступна к нажатию только после успешной валидации данных.
Хорошо, с простой формой мы разобрались, а как быть с формой посложнее? Усложним задачу. Будем делать импровизированную форму поиска статей для Хабра:
Мы имеем три фильтра, при выборе которых должны активироваться проверки заданных условий для каждого фильтра. Плюс активация контролов, которые относятся к выбранному фильтру. Хотелось бы отметить, что управление состоянием контролов не совсем относится к валидации данных, но в данном случае мы не будем заострять на этом внимание.
Активацию контролов будем делать так:
// список чекбоксов с категориями
var categoryCheckBoxes = pnlCategories.Controls.Cast<CheckBox>();
// управление состоянием контролов в зависимости от включенных чекбоксов
dtBegin.EnableByTimer(() => chkFilterByDate.Checked);
dtEnd.EnableByTimer(() => chkFilterByDate.Checked);
pnlCategories.EnableByTimer(() => chkFilterByCategory.Checked);
pnlTextFilter.EnableByTimer(() => chkFilterByText.Checked);
Теперь правила валидации. Если фильтр по дате включен, то начальная дата должна быть меньше либо равна конечной. Начальная дата не может быть раньше 1990 года. Валидация будет происходить в обоих DatePicker'ах, но индикация будет отображаться только на dtEnd:
dtEnd
.ValidateControl()
.IsTrue(ctl => !chkFilterByDate.Checked || dtBegin.Value >= new DateTime(1990, 1, 1),
"Начальная дата отбора не может быть раньше 1990 года")
.IsTrue(ctl => !chkFilterByDate.Checked || dtBegin.Value <= dtEnd.Value,
"Начальная дата должна быть меньше или равной конечной");
Если осуществляется фильтрация по категориям, то необходимо выбрать как минимум одну категорию:
pnlCategories
.ValidateControl()
.IsTrue(ctl => !chkFilterByCategory.Checked || categoryCheckBoxes.Any(c => c.Checked),
"Необходимо выбрать категорию");
Если осуществляется поиск текста, то необходимо задать текст и выбрать где его искать:
pnlTextFilter
.ValidateControl()
.IsTrue(ctl => !chkFilterByText.Checked || chkSearchTextInBody.Checked || chkSearchTextInHeader.Checked,
"Необходимо выбрать места поиска текста")
.IsTrue(ctl => !chkFilterByText.Checked || !string.IsNullOrWhiteSpace(txtSearchText.Text),
"Необходимо задать текст");
Также, для успешной валидации формы, должен быть задан хотя бы один из фильтров для поиска:
gbSearchParameters
.ValidateControl()
.IsTrue(ctl => chkFilterByCategory.Checked || chkFilterByDate.Checked || chkFilterByText.Checked,
"Необходимо задать условия поиска.");
Ну и по результатам валидации формы активируем главную действующую кнопку:
butSearch
.ValidateControl()
.EnableByValidationResult();
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Teleavtomatika.Forms;
namespace Teleavtomatika_Form_Validation
{
public partial class frmMain2 : Form
{
public frmMain2()
{
InitializeComponent();
// список чекбоксов с категориями
var categoryCheckBoxes = pnlCategories.Controls.Cast<CheckBox>();
// управление состоянием контролов в зависимости от включенных чекбоксов
dtBegin.EnableByTimer(() => chkFilterByDate.Checked);
dtEnd.EnableByTimer(() => chkFilterByDate.Checked);
pnlCategories.EnableByTimer(() => chkFilterByCategory.Checked);
pnlTextFilter.EnableByTimer(() => chkFilterByText.Checked);
// теперь правила валидации:
// если фильтр по дате включен, то начальная дата должна быть меньше либо равна конечной
// начальная дата не может быть раньше 1990 года
// валидация будет происходить в обоих DatePicker'ах, но индикация будет отображаться только на dtEnd
dtEnd
.ValidateControl()
.IsTrue(ctl => !chkFilterByDate.Checked || dtBegin.Value >= new DateTime(1990, 1, 1),
"Начальная дата отбора не может быть раньше 1990 года")
.IsTrue(ctl => !chkFilterByDate.Checked || dtBegin.Value <= dtEnd.Value,
"Начальная дата должна быть меньше или равной конечной");
// если осуществляется фильтрация по категориям
// то необходимо выбрать как минимум одну категорию
pnlCategories
.ValidateControl()
.IsTrue(ctl => !chkFilterByCategory.Checked || categoryCheckBoxes.Any(c => c.Checked),
"Необходимо выбрать категорию");
// если осуществляется поиск текста
// то необходимо задать текст
// и выбрать где его искать
pnlTextFilter
.ValidateControl()
.IsTrue(ctl => !chkFilterByText.Checked || chkSearchTextInBody.Checked || chkSearchTextInHeader.Checked,
"Необходимо выбрать места поиска текста")
.IsTrue(ctl => !chkFilterByText.Checked || !string.IsNullOrWhiteSpace(txtSearchText.Text),
"Необходимо задать текст");
// должен быть задан хотя-бы один из фильтров для поиска
gbSearchParameters
.ValidateControl()
.IsTrue(ctl => chkFilterByCategory.Checked || chkFilterByDate.Checked || chkFilterByText.Checked,
"Необходимо задать условия поиска.");
// Ну и по результатам валидации формы активируем главную действующую кнопку "Найти":
butSearch
.ValidateControl()
.EnableByValidationResult();
}
}
}
Посмотреть как это работает в живую можно на видео:
Исходники тут.
This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.
Комментариев нет:
Отправить комментарий