Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Валидация форм в декларативном жанре (C#)

Anna | 17.06.2014 | нет комментариев
Я думаю, что многие из вас сталкивались с задачей валидации данных в формах. Это длинно, изнурительно и Зачастую требует существенных усилий. Порой мне кажется, что ребята из Редмонта насмехаются над нами, предлагая проводить валидацию так. Шучу, безусловно, но данный способ мы применять не будем.

Мы будем изготавливать валидацию данных формы в механическом режиме, при помощи правил, описанных в декларативном жанре. Возьмем простейшую форму:



Тут есть несколько обыкновенных текстовых полей, поле ввода числа и поле для 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();
Полный код 2-й формы

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();
        }
    }
}

Посмотреть как это работает в живую дозволено на видео:

Исходники здесь.

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB