Гостевая
Форум
Разделы
Главная страница
Js скрипты
Php скрипты
Html шаблоны
Книги по Web дизайну
Статьи


Главная страница статей --> Хитрости при программировании php, заметки по базам данных

Лекция 5. AutoPostBack Привязка к данным. Коллекции. Проверка правильности вводимых данных.

Источник: realcoding.net

Свойство AutoPostBack


Программирование в ASP.NET ориентировано на события. События на странице, например, нажатие на кнопку, обрабатываются на сервере. Изменения в тексте поля редактирования, выбора опции в списке, нажатие на флажок или переключатель не вызывают немедленной отправки на сервер. Этого можно добиться, если установить свойство AutoPostBack для этих элементов.

Если AutoPostBack установлен для элемента управления TextBox, то для него будет вызываться событие TextChanged, как только поле потеряет фокус или будет нажата клавиша Enter. Чтобы это свойство работало, браузер должен поддерживать ECMAScript(стандарт JavaScript, принятый Европейской ассоциацией производителей компьютеров).

Источником данных для элементов управления могут служить таблицы данных. Давайте разберем пример, входящий в состав Visual Studio – CarSelectorSample. Дело происходит в электронном магазине автомобилей. Имеются разные марки машин, причем для каждой марки имеются несколько моделей. При выборе марки машины в первом списке во второй список автоматически грузятся соответствующие модели.

Brand Buick Chevrolet Pontiac Toyota Mileage Features
Power seat
Buick Century Impala Grand Am Avalon 0-10000 Leather seat
Chevrolet LeSabre Malibu Grand Prix Camry 10000-20000 Sun roof
Pontiac Park Avenue Metro Montana Camry Solara 20000-30000 CD player
Toyota Regal Prizm Sunfire Celica 30000 and more ABS

Все данные, используемые на этой странице, собраны в таблицу. Для хранения такой таблицы есть класс DataTable. Таблица состоит из столбцов – DataColumn и строк DataRow. Класс DataView позволяет создавать различные представления данных таблицы. Первый столбец служит источником данных списка марок. В зависимости от выбранной модели в список моделей загружается одна из 2-5 колонок.

Вначале создается таблица

Cars = new DataTable();
 
Cars.Columns.Add(new DataColumn(Brand, typeof(string)));

Здесь вызывается один из конструкторов DataColumn. Первый аргумент – название колонки, второй – тип.

CarRow = Cars.NewRow();

Создается новая строка таблицы. Ячейка таблицы задается с помощью индекса строки.

CarRow[6]= Power seat;

И строка добавляется в таблицу.

Cars.Rows.Add(CarRow);

У выпадающего списка марок установлено свойство AutoPostBack. Это значит, что страница автоматически подается на сервер, когда в этом списка меняется выбранный элемент.

В обработчике выбора нового элемента вначале выясняется, какой элемент выбран.

string selected = DropDownList1.SelectedItem.Value;

В операторе switch происходит переключение второго списка на один из столбцов таблицы заданием свойств DataTextField и DataValueField, где DataTextField – текст, отображаемый в списке, а DataValueField – выбранное значение. В данном случае, как часто бывает, они одинаковы.

Привязка к данным


Некоторые элементы управления: списки, таблицы и другие - имеют свойство DataSource, которое отвечает за привязку к данным. Тип этого свойства – object, то есть может быть любого типа, но этот тип должен реализовывать интерфейс IEnumerable. Часто значениями этого свойства назначают коллекции. В таком случае нет нужды добавлять значения вручную. Свойство DataSource может быть привязано к коллекциям, поддерживающим интерфейсы IEnumerable, ICollection или IListSource. Источником данных также могут быть XML-файлы, базы данных. Вызовом метода DataBind данные привязываются к элементу управления. Метод Page.DataBind вызывает привязку данных у всех элементов на странице.

Приведенный ниже выпадающий список помогает выбрать континент для путешествия. Источник данных – динамический массив ArrayList. Используйте его, если в программе происходит много вставок и удалений.

void Page_Load()
      {
         
ArrayList ContinentArrayList = new ArrayList();
         
ContinentArrayList.Add(Worldwide);
         
ContinentArrayList.Add(America);
         
ContinentArrayList.Add(Africa);
         
ContinentArrayList.Insert(1, Asia-Pacific);
         
ContinentDropDownList.DataSource = ContinentArrayList;
         
ContinentDropDownList.DataBind();
      }
//End Page_Load()
 
....
  <
asp:DropDownList id=ContinentDropDownList runat=server />

Можно использовать в качестве источника данных хеш-таблицы (Hashtable). Хеш-таблицы – это структуры данных, которые были придуманы давно(см. 3 том «Искусства программирования» Д.Кнута), но программисты долгое время были вынуждены реализовывать их вручную. В языке php обычный массив и есть хэш-таблица. В библиотеке STL для языка С++ тоже есть тип map, в котором данные хранятся таким способом. Хеш-таблицы позволяют очень быстро найти значение по ключу. Индекс в коллекции вычисляется как простая хэш-функция ключа. В C# ключи используются как индексаторы. Используйте Hashtable, если в программе часто осуществляется поиск. Вставка и удаление происходят в нем медленно. Ключи могут быть произвольного типа. В классе Object определен виртуальный метод GetHashCode, он и используется в Hashtable.

<%@ Page Language=C# %>
  <!
DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd>
  <
script runat=server>
 
void calSelectChange(Object sender, EventArgs e)
  {
      
lblShow.Visible = false;
      
Hashtable hshDays = new Hashtable();
      
hshDays[Convert.ToDateTime(2/6/2006)] = Экзамен по алгебре;
      
hshDays[Convert.ToDateTime(3/6/2006)] = Экзамен по С#;
      
hshDays[Convert.ToDateTime(4/6/2006)] = Начало изучения курса ASP.NET;
      
hshDays[Convert.ToDateTime(1/6/2006)] = День защиты детей;
      
DateTime datDateIn;
      
datDateIn = calDays.SelectedDate;
       if (
Page.IsPostBack)
       {
          
lblShow.Text = На этот день назначен: ;
          
lblShow.Text += hshDays[datDateIn];
           if (
hshDays[datDateIn] == null)
               
lblShow.Text = Ничего не назначено;
          
lblShow.Visible = true;
       }
  }
 
</script>
  <html xmlns=http://www.w3.org/1999/xhtml >
  <head runat=server>
      <title>Попробуем хэш-таблицу</title>
  </head>
  <body>
      <form id=form1 runat=server>
      <div>
      <h3>Ежедневник
  </h3>
  Введите дату между 1/6/2006 и 30/6/2006
  <asp:Calendar id=calDays runat=server 
  OnSelectionChanged=calSelectChange
  VisibleDate=06/06/2006
  ></asp:Calendar>
  <br />
  <br />
  <asp:Label id=lblShow runat=server></asp:Label>
      </div>
      </form>
  </body>
  </html>

Здесь ключом хэш-таблицы является дата. Convert.ToDateTime конвертирует строку в тип даты. VisibleDate гарантирует, что на календаре будет июнь 2006 года. Если значений по ключу в таблице нет, то индексатор просто возвращает null. Значения можно вводить в любом порядке.

Хотелось бы добавить в страницу новую возможность введения новых записей. Можно ввести новые элементы управления – строку ввода и кнопку для подачи данных. При обработке нажатия на кнопку добавим в хэш-таблицу новое значение.

void Button1_Click(object sender, EventArgs e)
      {
         
hshDays[calDays.SelectedDate]=TextBox1.Text;
      }

Эта страница не работает. Дело в том, что страница загружается заново, когда меняется дата. Хэш-таблица создается заново, и введенные в нее значения теряются. Как же решить эту проблему? Сделаем хэш-таблицу статической переменной.

static Hashtable hshDays;
 
void calSelectChange(Object sender, EventArgs e)
  {
      
DateTime datDateIn = calDays.SelectedDate;
      
lblShow.Text = На этот день назначен: ;
      
lblShow.Text += hshDays[datDateIn];
      if (
hshDays[datDateIn] == )
         
lblShow.Text = Ничего не назначено;
  }
 
void Page_Init()
  {
      if (!
Page.IsPostBack)
      {
         
hshDays=new Hashtable();
         
hshDays[Convert.ToDateTime(2/6/2006)] = Экзамен по алгебре;
         
hshDays[Convert.ToDateTime(3/6/2006)] = Экзамен по С#;
         
hshDays[Convert.ToDateTime(4/6/2006)] = Начало изучения курса ASP.NET;
         
hshDays[Convert.ToDateTime(1/6/2006)] = День защиты детей;
         
Session[Diary]= hshDays;
       }
  }
 
void Record(Object sender, EventArgs e)
  {
      
DateTime datDateIn = calDays.SelectedDate;
      
hshDays[datDateIn]= Entrance.Text;
      
lblShow.Text = hshDays[datDateIn].ToString();
  }

Классы проверки данных (Валидаторы)


Данные из форм обычно записываются в базы данных, и тип информации в них должен соответствовать типу и длине данных в полях таблиц баз данных. Кроме того, иногда нужно вводить взаимосвязанные данные, например пароль во время регистрации нужно вводить 2 раза, и он в обоих полях должен совпадать. Некоторые хакеры пытаются вводить в формы программные коды, чтобы взломать вашу систему. Бдительность и еще раз бдительность, как говорил товарищ... не помню кто. А если пользователь ввел неверные данные случайно, сервер выдаст непонятное сообщение об ошибке, и ценный клиент уйдет с нашего сайта на другой.

Прежде чем работать с данными, нужно убедиться, что:

* В определенное поле введена информация;
* Текст в поле адрес имеет форму электронного адреса(с @ и с точкой);
* Дата рождения разумна, например, пользователь не сообщил о себе, что ему 300 лет или 1 годик.
* Пароль достаточно сложен и не совпадает с логином.

Проверка может происходить и на стороне клиента, и на сервере. При валидации на стороне клиента в страницу встраивается код на Javascript. Если данные в форме не проходят проверку, страница просто не будет отправлена на сервер. Таким образом избежим лишнего трафика и не будем загружать сервер. С другой стороны, валидации на стороне сервера более надежна. Javascript-код хакеры могут легко посмотреть и отправить неправильные данные, которые пройдут эту проверку. Наконец, Javascript можно просто выключить в настройках браузера. При валидации на стороне сервера данные проверяются программой на полноценном языке. Ее код пользователю неизвестен. В результате проверки генерируется новая страница с сообщениями об ошибках. Самая разумная стратегия – применять комбинацию этих методов. Предварительная проверка у клиента защитит от опечаток, а серьезная проверка на сервере – от злонамеренного взлома.

Существует целый ряд серверных элементов управления, которые не занимаются выводом информации, а проверяют данные, введенные пользователем. ASP.NET 2.0 сам определяет тип браузера и генерирует наиболее подходящий для данного случая код, который. Если браузер поддерживает Javascript-код, который он может послать, то валидация или ее часть происходит на стороне клиента. Если браузер не поддерживает Javascript, то вся валидация происходит на сервере.

Получить доступ к валидаторам просто – раскройте в Toolbox вкладку Validation.

Класы валидаторов образуют иерархию, во главе которой стоит абстрактный класс BaseValidator.



Базовый класс валидаторов сам наследник класса Label, так что по существу все валидаторы - метки, текст в которых становится видимым, когда не выполняются определеннные нами условия проверки. По умолчанию текст в валидаторах красный. (Вспомните школу и замечания учительнице в тетради). Но конечно же, этот цвет поменять на более приятный. Все валидаторы имеют свойство ControlToValidate. Оно задает тот контрол, данные в котором проверяются данными валидатором. Этот элемент должен находиться в одном контейнере с валидатором.
Общие свойства валидаторов
Display Предоставлять ли место статически или динамически
EnableClientScript Разрешать ли генерировать клиентский код
ErrorMessage Текст сообщения об ошибке
IsValid Прошел ли валидацию связанный с валидатором элемент
Инициация проверки данных

Проверка всегда инициируется каким-либо событием. Обычно это щелчок на кнопках Button, ImageButton, LinkButton, в которые по умолчанию свойство CausesValidation установлено в true. Можно убрать это свойство для некоторых кнопок, которым оно не нужно, например, кнопки Cancel.

В примере с автосалоном на странице имеются несколько валидаторов.

<asp:requiredfieldvalidator id=RequiredFieldValidator2 runat=server 
                         
ErrorMessage=Required 
                         
ControlToValidate=DropDownList1>
                                                 </
asp:requiredfieldvalidator>

Класс RequiredFieldValidator проверяет, было ли изменено значение в связанном с ним элементе управления. Если, как в данном случае, это выпадающий список, первоначально выбрано пустое значение, но требуется, чтобы пользователь выбрал конкретную марку. Если не выбрал, но нажал кнопку submit, валидация проваливается и выводится текст, заданный в ErrorMessage или в Text. Валидаторы отображают текст указанный в свойстве "Text", всегда, когда оно не пусто, а текст установленный в свойстве "ErrorMessage", тогда, когда свойство "Text" равно "". Первоначальное значение задается свойством InitialValue. Если это свойство не задано, то проверка проводится на отсутствие значения (например, пустой Textbox).

Для проверки корректности ввода электронного адреса используется класс RegularExpressionValidator.

<span class=label>Your Email</span><span class=label1>&nbsp;(Required)</span>&nbsp;
  <
asp:textbox id=TextBox1 runat=server></asp:textbox>         &nbsp;
  <
asp:RegularExpressionValidator id=RegularExpressionValidator1 runat=server ControlToValidate=TextBox1 ErrorMessage=Not a valid Email ValidationExpression=w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*></asp:RegularExpressionValidator>
  <
asp:RequiredFieldValidator id=RequiredFieldValidator1 runat=server ControlToValidate=TextBox1 ErrorMessage=*></asp:RequiredFieldValidator>
  </
span>

ValidationExpression – регулярное выражение, на соответствие которому проходит проверку значение текстового поля. в Visual Studio 2005 предоставляет несколько готовых шаблонов регулярных выражений, которые можно выбрать в окне свойств – телефонных номеров разных стран, адресов, и, самое полезное, шаблоны электронной почты и адреса в интернете.

С одним элементом управления может быть связано несколько валидаторов. Например, электронный адрес проверяется и на соответствие шаблону, и на обязательное заполнение.

Свойство Page.IsValid позволяет определить, прошла ли вся страница валидацию. Для браузеров, которые поддерживают DHTML, проверка происходит на стороне клиента. Для этого автоматически генерируется JavaScript-код. Таким образом экономятся ресурсы сервера и трафик, которые бы пришлось потратить на передачу неправильных данных.

Валидаторы сравнения


CompareValidator сравнивает значение со значением в другом элементе управления или с константой. Также можно проверить, можно ли конвертировать значение в связанном с ним элементе управления в какой-либо тип.

Свойство Operator позволяет установить операцию, посредством которой происходит сравнение: Equal, NotEqual, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual. Значение DataTypeCheck означает проверку на соответствие типу.

Свойство Type может принимать значения String, integer, Date, Double и Currency.

Свойство ControlToCompare задает элемент управления, с которым происходит сравнение. ValueToCompare задает значение. Из этих двух свойств установленным может быть только одно.

RangeValidator проверяет соответствие введенного значения диапазону, заданному своствами MinValue и MaxValue.

<asp:TextBox ID=TextBox1 runat=server></asp:TextBox>
  <
asp:RangeValidator ID=RangeValidator1 runat=server 
      
ControlToValidate=TextBox1
      
ErrorMessage=Не больше 10 бутылок пива в одни руки 
      
MaximumValue=10 MinimumValue=1 Type=Integer>
  </
asp:RangeValidator>

ValidationSummary

Класс ValidationSummary позволяет вывести итоговую информацию по всем валидаторам на странице. Она может быть выведена в различной форме:

* BulletList – список со значками
* List – обычный список
* SingleParagraph – простой параграф

Информацию можно выводить на странице, а можно в информационном окне, если ShowMessage поставить в True. Для всех валидаторов выводится свойство Error Message, а не текст. Text выводится в самом валидаторе.

Вернемся к странице Registration.aspx. Добавим в него еще одно поле для ввода пароля.

<form runat=server id=input>
      <
asp:Label ID=Label1 runat=server Text=Введите имя: Width=140px></asp:Label>
  <
asp:TextBox ID=txtName runat=server CausesValidation=True />
      <
asp:Label ID=Label2 runat=server Text=Введите адрес: Width=140px></asp:Label>
  <
asp:TextBox id=txtAddress runat=server textmode=multiline rows=5
 
/>
  <
br/><br />
      <
asp:Label ID=Label3 runat=server Text=Введите пароль: Width=140px></asp:Label>
      <
asp:TextBox id=txtPassword runat=server textmode=password />
      <
br />
  <
br />
      <
asp:Label ID=Label4 runat=server Text=Повторите пароль Width=140px></asp:Label>
      <
asp:TextBox id=TextBox1 runat=server textmode=password /><br />
     <
asp:Button ID=Button1 runat=server Text=Submit />
  </
form>

Свойство CausesValidation работает, когда элемент управления теряет фокус. В таком случае связанный с ним валидатор показывает значение своего свойства Text.

Нам нужно, чтобы имя было обязательно введено, а пароль совпадал в обоих текстовых полях.

Перетащите RequiredFieldValidator и бросьте его на форму. ControlToValidate установите в txtName. Второй валидатор – RequiredFieldValidator для пароля. Третий – CompareValidator, который сравнивает значение паролей.

<asp:RequiredFieldValidator ID=RequiredFieldValidator1 ControlToValidate=txtName
      
Display=Static ErrorMessage=Имя необходимо ввести runat=server >*</asp:RequiredFieldValidator>
          <
asp:RequiredFieldValidator ID=RequiredFieldValidator2 runat=server ErrorMessage=Пароль не должен быть пустым ControlToValidate=txtPassword1>*</asp:RequiredFieldValidator>
  <
asp:CompareValidator ID=CompareValidator1 runat=server
      
ControlToValidate=txtPassword1
      
ErrorMessage=Пароли должны совпадать! ControlToCompare=txtPassword2></asp:CompareValidator><br />

А также один ValidationSummary:

<asp:ValidationSummary ID=ValidationSummary1 runat=server />

Поставим кнопку, при нажатии на которую будет происходить проверка.

<asp:Button ID=Button1 runat=server Text=Валидация OnClick=Validate_Click />

Обработчик нажатия на кнопку подтверждает ввод, если валидация прошла успешно:

protected void Validate_Click(object sender, EventArgs e)
      {
          if (
Page.IsValid)
          {
             
lblName.Text = ;
             
lblAddress.Text = ;
             
lblPassword.Text = ;
             
input.Visible = false;
              if (
txtName.Text != )
                  
lblName.Text = Вы ввели имя: + txtName.Text;
              if (
txtAddress.Text != )
                  
lblAddress.Text = Вы ввели адрес: +
             
txtAddress.Text;
              if (
txtPassword1.Text != )
                  
lblPassword.Text = Вы ввели пароль: +
                     
txtPassword1.Text + <br>Спасибо за регистрацию!;
          }
      }

Вся проверка этой страницы происходит у клиента. Можете даже остановить сервер, чтобы в этом убедиться. Только когда все данные введены правильно, происходит отправка формы на сервер.
CustomValidator

Если нужно сделать такую проверку, которую не получается осуществить с помощью стандартных валидаторов, в игру вступает CustomValidator. В классе CustomValidator можно написать любую функцию, которая будет проверять значения как на стороне сервера, так и у клиента. Классический пример – проверка числа на четность.

Напишем пользователький валидатор, который будет проверять пароль на длину – не меньше 5 символов.

<head>
      <
title>Регистрация нового пользователя</title>
  <
script language=JavaScript>
  function
validatePassword(oSrc, args)
  {
      
args.IsValid = (args.Value.length > 5); 
  }
 
</script>
  </head>
  ......
      <asp:CustomValidator ID=CustomValidator1 runat=server 
          ControlToValidate=txtPassword1
          ErrorMessage=Слишком короткий пароль Display=Static
          ClientValidationFunction=validatePassword >*</asp:CustomValidator>

Проверка происходит на стороне клиента функцией на JavaScript validatePassword. Для этого надо в свойстве ClientValidationFunction записать имя функции. В сгенерированном коде к кнопке привязан такой код:

<input type=submit name=Button1 value=Button onclick=javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;Button1&quot;, &quot;&quot;, true, &quot;&quot;, &quot;&quot;, false, false)) id=Button1 />

Известно, что если функция, связанная с onclick, вернет логическое значение false, форма не будет отправлена на сервер.

<asp:CustomValidator ID=CustomValidator1 runat=server 
         
ControlToValidate=txtPassword1
         
ErrorMessage=Слишком короткий пароль Display=Static
         
OnServerValidate=ServerValidate >*</asp:CustomValidator><br />

Произведем такую же валидацию на сервере. Чтобы запустить проверку на сервере, используется свойство OnServerValidate. Функция, которая указана в ней, входит в класс страницы и должна быть написана на C#:

void ServerValidate(object source, ServerValidateEventArgs args)
      {
         
string password = args.Value.ToString();
         
int len = password.Length;
         
args.IsValid = (len >= 5);
      }

ServerValidate вызывается после события Page_Load, поэтому нельзя, как в лекции 3, выводить результаты в Page_Load.

Можно также одновременно проводить и клиентскую, и серверную валидацию:

<asp:CustomValidator ID=CustomValidator1 runat=server 
         
ControlToValidate=txtPassword1
         
ErrorMessage=Слишком короткий пароль Display=Static
         
OnServerValidate=ServerValidate 
         
ClientValidationFunction=validatePassword >*</asp:CustomValidator>

Чтобы отключить возможность генерации клиентского кода для всех валидаторов, можно написать:

void Page_Load()
      {
          foreach (
BaseValidator bv in Page.Validators)
          {
             
bv.EnableClientScript = false;
          }
      }

Для отображения сообщения об ошибке можно использовать звуки и картинки. Для этого в свойство ErrorMessage нужно записать не текст, а соответствующих тег HTML, например:

ErrorMessage=<img src=error.gif>

Группы валидации.

Иногда бывает нужно иметь на странице несколько кнопок, и при нажатии на каждую вводится информация из логически взаимосвязанных групп элементов управления. Поэтому должны проверяться значения только из этой группы. У всех валидаторов и элементов управление, через которые возможен ввод информации, есть свойство ValidationGroup. Функцию Page.Validate() тоже можно использовать с таким параметром. Если происходит нажатие на кнопку с установленным ValidationGroup, запускается проверка тех валидаторов, у которых это свойство такое же.

Заключение


Назначение форм в том, чтобы получать данные от пользователей, но данные не имеют смысла, если они введены неправильно. Элементы-валидаторы позволяют автоматизировать рутинные действия по проверке данных и гарантировать ввод данных, соответствующих нашим требованиям.



Похожие статьи:
- XML+MSSQL+ASP.NET. Часть 1.
- Концептуальный подход к дизайну сайта
- Разница между HttpModule и HttpHandler
- Очищаем HTML от лишних знаков
- Обзор DetailsView
- Лекция 6. Работа с базами данных.
- Лекция 2. Анатомия ASP.NET. ASP.NET в действии.
- Рекомендации по продвижению малых сайтов
- Использование AJAX в ASP.NET
- Полезные советы для работы с XML
- XML-RPC на языке Python
- Использование ext/mysqli: Часть I - Обзор и подготовленные выражения
- Практическое применение ООП в PHP5


Оглавление | Обсудить на форуме | Главная страница сайта | Карта сайта |
[0.001]