(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

ASP.Net. Лекция 8. Элементы-потребители данных (Data-Bound Controls) (исходники)

Асмик Гаряка

Лекция 7

Потребители данных отображают данные, полученную из классов источников данных. Они дают большую функциональность. Например, элемент управления GridView может не только показывать данные, но и сортировать, выбирать, редактировать их. Если этой функциональности недостаточно, ее можно расширить, написав собственные обработчики событий.

Элементы, которые могут быть связаны с элементами-источниками данных, многообразны. Во-первых, это уже хорошо знакомые DropDownList, ListBox, CheckBoxList, RadioButtonList, BulletedList. Однако, у всех них необходимо в качестве источника данных указывать не DataSource, а DataSourceID. Все эти элементы отображать могут только 1 поле, указанное в DataTextField, с возможностью задания второго в качестве индексного в свойстве DataValueField.

  <asp:SqlDataSource ID="SqlDataSource3" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" 
      SelectCommand="SELECT [CategoryName], [CategoryID] FROM [Categories]"> 
  </asp:SqlDataSource> 
  <asp:CheckBoxList ID="CheckBoxList1" runat="server" AppendDataBoundItems="True" DataSourceID="SqlDataSource3" 
      DataTextField="CategoryName" DataValueField="CategoryID"> 
  </asp:CheckBoxList>  
  <asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="SqlDataSource3" DataTextField="CategoryName"> 
  </asp:DropDownList> 
  <asp:BulletedList ID="BulletedList1" runat="server" BulletStyle="UpperRoman" DataSourceID="SqlDataSource3" 
      DataTextField="CategoryName" DataValueField="CategoryName"> 
  </asp:BulletedList> 
  

AppendDataBoundItems - это новое свойство. Оно позволяет комбинировать данные из элемента-источника с данными, статически объявленными на странице.

Очень интересны элементы управления Repeater и DataList. Они позволяют управлять отображением данных с помощью шаблонов.

Синтаксис динамического связывания

Можно получать данные, связанные с элементом управления, в его декларации на странице. Это делается с помощью разновидности блока отображения. В ранних версиях ASP .NET с помощью такого механизма можно было только читать, но теперь возможно и двустороннее связывание. Особенно это важно в элементах управления, использующих шаблоны. Хотя DataGrid и GridView автоматически отображают данные, но и в них для создания нужных эффектов используются столбцы-шаблоны.

Для привязки к данным используются разделители <%# %>. В жизненном цикле каждого элемента управления наступает событие DataBinding, во время которого и вычисляются все выражения, заключенные в этот тег.

Если в функции Page_Load мы писали

          ContinentDropDownList.DataSource = ContinentArrayList;
  

То на странице это можно сделать с помощью

  <asp: DropDownList id=" ContinentDropDownList " datasource='<%# ContinentArrayList %>' runat="server">
  

В ASP .NET 1.x данные читались в объекты DataSet или DataReader, после чего вызывался DataBind. в ASP.NET 2.0, если же установлено свойство DataSourceID, то событие DataBinding вызывается автоматически.

В сгенерированном ASP.NET классе страницы в обработчике этого события для ContinentDropDownList будет выполняться код

datasource = ContinentArrayList;

При этом в локальном кеше создается копия прочтенных данных. Для элементов Repeater, DataList, DataGrid синтаксис привязки данных разбирается в событии ItemDataBound, для GridView - в RowDataBound. Эти события вызываются столько раз, сколько записей в источнике данных. Каждый раз, когда ASP.NET встречает эти разделители в шаблоне, внутри элемента Item (RepeaterItem, DataListItem, DataGridItem) создается элемент типа DataBoundLiteralControl, внутри которого записывается выражение внутри разделителей. В обработчике события DataBinding этого элемента определена переменная Container, которая указывает на этот самый Item, то есть секцию элемента. Классы Item хранят данные в свойстве DataItem. Поэтому в шаблонах доступ к данным происходит с помощью синтаксиса Container.DataItem.

Возможный синтаксис для доступа к полю

  <%# ((System.Data.DataRowView)Container.DataItem)["City"]%>
  

в случае, когда данные получены из DataReader,

  <%# ((System.Data.IDataRecord)Container.DataItem)["City"]%>
  

в случае, когда данные получены из DataSet,

  <%# DataBinder.Eval(Container.DataItem, "City") %>
  

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

  DataBinder.Eval(Container.DataItem, "Age","{0:2d}")
  

В ASP .NET 2.0 синтаксис можно упростить и написать

  <%# Eval("City")%>
  

В новых элементах управления GridView, DetailsView, FormView, где поддерживается двунаправленный вывод данных, можно вызывать метод Bind. Его используют в шаблонах редактируемых строк.

  <asp:TextBox ID="EditFirstNameTextBox" RunAt="Server" Text='<%# Bind("FirstName") %>' />
  

Repeater

Repeater в переводе означает «тот, кто повторяет». Среди его значений «студент-второгодник» и «вор-рецидивист». Ведь они тоже повторяют, то что делают. Но это плохие значения, а хорошее - элемент-повторитель заданного шаблона для всех полей источника данных.

Шаблон - это множество тегов HTML и серверных элементов управления, которые задают образец для отображения составной части сложного элемента управления. DataGrid может использовать шаблоны или нет, но Repeater без них существовать не может, сам по себе он не имеет визуального представления. Таким образом, программист сам определяет его внешний вид. Кроме DataSourceID и DataMember, собственных свойств у него нет. Поэтому у программиста есть полный контроль над тем, как выводится Repeater.

Как минимум, должен быть описан шаблон ItemTemplate. HeaderTemplate отображается один раз в начале отрисовки рипитера, FooterTemplate в конце, SeparatorTemplate между отображением каждого пункта, AlternatingItemTemplate - для четных пунктов. Все серверные элементы управления в шаблоне помещаются целиком, поэтому чтобы получить таблицу, используют простые теги HTML. Например, открывающий тег <table> помещают в HeaderTemplate, а закрывающий в FooterTemplate.

В этом примере составляются характеристики сотрудников

  <asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1" > 
      <HeaderTemplate><asp:Label runat="server" ID="Header1"  
          BackColor="DarkOrange" ForeColor="ActiveCaptionText" 
          Font-Bold="true" Font-Underline="true" Font-Size="Large"> 
          We present our valued Employees!</asp:Label> 
          <table> 
      </HeaderTemplate> 
      <ItemTemplate> 
          <tr> 
           <td> 
             <asp:Panel ID="Panel1" runat="server" BackColor="LightPink"> 
      <asp:Image ID="Photo" runat="server" ImageUrl=<%# Eval("PhotoPath")%>/> 
                 <%# Eval( "TitleOfCourtesy") %> 
                 <%# DataBinder.Eval(Container.DataItem, "FirstName") %> 
                 <%# DataBinder.Eval(Container.DataItem, "LastName") %> 
                 was born in <%# Eval("BirthDate","{0:dd.MM.yyyy}") %>.<p> 
                 <%# Eval("TitleOfCourtesy").ToString() == "Mr." // Eval("TitleOfCourtesy").ToString() == "Dr." ? "He" : "She"%> 
                 lives in beautiful city  
                 <%# ((System.Data.DataRowView)Container.DataItem)["City"]%>, 
                 <%# Eval( "Region") %> in 
                 <%# DataBinder.Eval(Container.DataItem, "Country") %>.</p> 
                 <p>We appreciate <%# Eval("TitleOfCourtesy").ToString() == "Mr." //
  Eval("TitleOfCourtesy").ToString() == "Dr." ? "his" : "her"%> work as <%# Eval("Title") %>.</p> 
                 <p><%# DataBinder.Eval(Container.DataItem, "Notes") %></p> 
              </asp:Panel> 
           </td> 
         </tr> 
      </ItemTemplate> 
      <FooterTemplate> 
      </table></FooterTemplate> 
  </asp:Repeater>  
  <asp:SqlDataSource ID="SqlDataSource1" runat="server"  
          ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString1 %>" 
          SelectCommand="SELECT * FROM [Employees]" ></asp:SqlDataSource> 
  

В браузере это выглядит так:

Обратите внимание на условные выражения:

  <%# Eval("TitleOfCourtesy").ToString() == "Mr." // Eval("TitleOfCourtesy").ToString() == "Dr." ? "He" : "She"%>
  

Этим достигается тот эффект, что в предложении о мужчине употребляются местоимения мужского, а о женщине - женского рода. В таблице нет поля для пола, но его можно вычислить по TitleOfCourtesy, который у мужчин бывает или "Mr. ", или "Dr.".

Если нужно изменить внешний вид всего шаблона, проще всего поместить все его содержимое или весь элемент в Panel и определить в нем стили.

С помощью элемента управления Repeater можно создавать этикетки для конвертов, пригласительные билеты и так далее.

DataList

DataList имеет те же черты, что и Repeater, то есть выводит данные согласно шаблонам. Однако это более богатый элемент управления. Во-первых, он поддерживает выбор, редактирование, удаление и вставку. Поэтому список шаблонов пополнился SelectedItemTemplate и EditItemTemplate. Кроме того, у него есть верхний и нижний колонтитулы со стилями HeaderStyle и FooterStyle.

Во-вторых, можно изменить способы отображения. По умолчанию DataList выводит данные поколонно в таблице. Свойство RepeatLayout установленное как Flow, убирает табличные теги из выходного потока. RepeatDirection меняет направление вывода с вертикального на горизонтальное. RepeatColumns задает количество столбцов таблицы, по умолчанию равное 1.

DataList наследник абстрактного класса BaseDataList, который наследует WebControl. Поэтому у него в отличие от Repeater, имеются визуальные свойства. При отображении он представляет собой таблицу, поэтому присутствуют свойства CellPadding и CellSpacing.

У DataList есть шаблон по умолчанию, Visual Studio 2005 и VWD создают его в виде вертикально расположенных меток для каждого поля, а слева от них текст с названием поля. Чтобы войти в режим редактирования шаблона, нужно воспользоваться возможностью SmartTag - Edit Templates. После того, как редактирование окончено, не забудьте выйти из режима - End Template Editing.

Можно спроектировать этот элемент так, чтобы в обычном состоянии отображалась краткая информация, а в выбранном состоянии - более подробная.

Посмотрим пример из Quickstarts:

      <asp:DataList id="DataList1" runat="server" 
          BorderColor="black" BorderWidth="1" 
          GridLines="Both" CellPadding="3" 
          Font-Names="Verdana" Font-Size="8pt" 
          Width="150px" 
          HeaderStyle-BackColor="#aaaadd" 
          AlternatingItemStyle-BackColor="Gainsboro" 
          SelectedItemStyle-BackColor="yellow" 
          OnItemCommand="DataList_ItemCommand" 
       > 
      <HeaderTemplate> 
           Items 
      </HeaderTemplate> 
      <ItemTemplate> 
          <asp:LinkButton id="button1" runat="server" Text="Show details" CommandName="select" /> 
          <%# DataBinder.Eval(Container.DataItem, "StringValue") %> 
      </ItemTemplate> 
      <SelectedItemTemplate> 
        Item: 
          <%# DataBinder.Eval(Container.DataItem, "StringValue") %> 
          <br> 
        Order Date: 
          <%# DataBinder.Eval(Container.DataItem, "DateTimeValue", "{0:d}") %> 
          <br> 
        Quantity: 
          <%# DataBinder.Eval(Container.DataItem, "IntegerValue", "{0:N1}") %> 
        <br> 
      </SelectedItemTemplate> 
  </asp:DataList> 
  

А обработчик выбора записи такой:

      void DataList_ItemCommand(object Sender, DataListCommandEventArgs e) { 
          string cmd = ((LinkButton)e.CommandSource).CommandName; 
          if (cmd == "select") 
              DataList1.SelectedIndex = e.Item.ItemIndex; 
          BindList(); 
      } 
  

Чтобы реализвать редактирование, тоже нужно обрабатывать событие. Поэтому в ASP.NET 2.0 DataList лучше использовать для показа данных без редактирования, а если требуется редактирование, использовать элемент управления FormView.

Свойство DataKeyField имеется и у DataGrid, и у DataList. С помощью него происходит связывание с ключевым полем таблицы данных.

DataGrid

Это очень популярный элемент управления, и неудивительно. Особенно много он применялся в ASP.NET 1.x, но теперь его функции перекрываются GridView. Тем не менее его стоит изучить, так как многие его свойства схожи со свойствами GridView. DataGrid делает очень легким представление табличной информации, которая содержится в базах данных, файлах XML, или создается вручную. Достаточно создать DataGrid, установить свойство DataSource, и получить готовую таблицу на странице. Формат таблицы можно менять независимо от данных. Данные можно сортировать, выбирать, редактировать.

В простейшем варианте нужно установить только свойство DataSource, его значением может быть объект, реализующий интерфейс IEnumerable, например SqlDataReader, DataTable. При этом на странице выводится таблица, где строкам соответствуют записи, а столбцам поля.

Создадим простой XML-файл с табличной информацией. Это будут данные о лауреатах Нобелевской премии по литературе и физике. Назовите ее nobel.xml.

  <?xml version="1.0" encoding="utf-8" ?> 
  <nobel> 
    <phisics> 
      <phisisist> 
        <name>Basov</name> 
        <nationality>Russia(USSR)</nationality> 
      </phisisist> 
      <phisisist> 
        <name>Rentgen</name> 
        <nationality>Germany</nationality> 
      </phisisist> 
      <phisisist> 
        <name>Bor</name> 
        <nationality> Denmark</nationality> 
      </phisisist> 
    </phisics> 
    <literature> 
      <writer> 
        <name>Boris Pasternak</name> 
        <nationality>Russia</nationality> 
        <work>"Doctor Zhivago"</work> 
        <winningdate>1958</winningdate> 
      </writer> 
      <writer> 
        <name>Romain Rollan</name> 
        <nationality>France</nationality> 
        <work>"Jean-Cristophe"</work> 
        <winningdate>1915</winningdate> 
      </writer> 
      <writer> 
        <name>Gabriel Garsia Marquez </name> 
        <nationality>Columbia</nationality> 
        <work>"100 years of solitude"</work> 
        <winningdate>1982</winningdate> 
      </writer> 
      <writer> 
        <name>George Bernard Shaw</name> 
        <nationality>Great Britain</nationality> 
        <work></work> 
        <winningdate>1925</winningdate> 
      </writer> 
    </literature> 
  </nobel> 
  

Тут построена трехуровневая иерархия. Узел <nobel> должен быть прочитан в DataSet. Внутри него есть 2 узла - один с данными о физике, второй о литературе. Каждый из них будет помещен в DataTable. Узлы <name>, <nationality>, <work>, <winningdate> вложены в <literature> и повторяются для каждого писателя. Они будут считаны в DataColumns таблицы.

Почему узел <work></work> у Шоу пустой? Как считал сам Шоу, Нобелевскую премию 1925 года ему дали за то, что в этом году он ничего не написал.

Через методы ReadXml, WriteXml DataSet может читать данные из XML-файла.

Форма, которая читает информацию из этого файла:

  <%@ Page Language="C#" Debug="true" %> 
  <%@ Import Namespace="System.Data" %> 
  <%@ Import Namespace="System.Xml" %> 
  <script runat="server"> 
      void Page_Load() 
      { 
          String xmlFilename = Server.MapPath("") + "\\nobel.xml"; 
          DataSet newDataSet = new DataSet(); 
          newDataSet.ReadXml(xmlFilename); 
          DataTable newDataTable = newDataSet.Tables[1]; 
          DataGrid1.DataSource = newDataTable; 
          DataGrid1.DataBind(); 
      } 
      void Page_Load() 
      { 
          if (!IsPostBack) 
              bindData(); 
      } 
  </script> 
  <html xmlns="http://www.w3.org/1999/xhtml"> 
  <head> 
      <title>Data Grid Control example</title> 
  </head> 
  <body> 
      <form runat="server"> 
          <asp:DataGrid id="DataGrid1" runat="server" CellSpacing="10" 
          BorderWidth ="0"  BackColor="AliceBlue" EditItemIndex = "1"> 
          <HeaderStyle BackColor="#AAAADD" Font-Size="20pt" Font-Bold = "True"> 
          </HeaderStyle> 
          <AlternatingItemStyle BackColor="#80FF80" /> 
      </form> 
  </body> 
  </html> 
  

Поменяв индекс в DataTable newDataTable = newDataSet.Tables[1] на 3, получим страницу с другими данными - лауреатов премии по литературе.

По умолчанию элемент DataGrid сам определяет количество полей в источнике данных и генерирует колонки таблицы. Это определяется свойством AutoGenerateColumns. С элементом управления DataGrid могут быть связаны не все типы данных. Поддерживаются примитивные типы, строки, DataTime и Decimal. Если в поле неподдерживаемый тип, столбец не будет создан. Если ни одного подходящего поля нет, будет выброшено исключение.

DataGrid имеет заголовок (Header), который по умолчанию виден, и нижний колонтитул (Footer). При автоматической генерации в заголовке каждого столбца выводится название поля.

Если AutoGenerateColumns установить в False, можно самим управлять колонками и определять более сложный его вид. В таком случае надо включать в DataGrid элементы BoundColumn. Некоторые свойства BoundColumn:

DataField определяет поле источника данных.

DataFormatString задает формат вывода данных.

ReadOnly делает поле недоступным для редактирования.

В заголовке и нижнем колонтитуле можно установить любой текст, а в заголовке еще и картинку(HeaderText, FooterText, HeaderImageUrl).

В ячейку генерируемой DataGrid таблицы вставляется LiteralControl, текст которого берется из источника данных и форматируется в соответствии с DataFormatString. Для редактируемой строки в ячейке появляется TextBox.

Есть и другие типы колонок.

ButtonColumn отображает в каждой строке командную кнопку. Если связать ее с полем, на кнопках будут надписи из этого поля.

EditCommandColumn показывает кнопки для редактирования.

HyperLinkColumn превращает текст в гиперссылки. Например, поле PhotoPath можно показать в такой колонке, тогда щелчок по ссылке покажет фотографию.

TemplateColumn позволяет определить шаблон отображения, как в DataList.

При желании можно программно скрывать и показывать колонки, например:

  DataGrid1.Columns[1].Visible = !(DataGrid1.Columns[1].Visible);
  

У элемента DataGrid есть 7 свойств, задающих стили различных его частей или типов строк. Все они имеют тип TableItemStyle. Это AlternatingItemStyle, EditItemStyle, FooterStyle, HeaderStyle, ItemStyle, PagerStyle, SelectedItemStyle. Стили образуют иерархию, то есть атрибут стиль, который выше в иерархии, наследует те, которые ниже, если он его не переопределяет. Порядок в ней такой:

  1. EditItemStyle - стиль редактируемой строки;
  2. SelectedItemStyle - стиль выбранной строки;
  3. AlternatingItemStyle это стиль каждой второй строки.
  4. ItemStyle - стиль строки по умолчанию
  5. ControlStyle - это все свойства, которые влияют на внешний вид элемента, например BackColor. PagerStyle, FooterStyle, HeaderStyle тоже его наследуют.

PagerStyle - это стиль пейджера, то есть номеров страниц-гиперссылок, при выборе которых таблица перелистывается. Чтобы пейджер появился, должен быть установлен атрибут AllowPaging и количество записей должно быть больше PageSize. Все эти свойства удобно устанавливать с помощью PropertyBuilder.

В Visual Studio 2005 есть возможность автоформатирования, как и у DataList.

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

  <asp:DataGrid ID="DataGrid2" runat="server" BackColor="#FFE0C0" ShowFooter="True" AutoGenerateColumns="False" PageSize="3"> 
      <AlternatingItemStyle BackColor="#C0FFC0" /> 
      <ItemStyle BackColor="#FFFFC0" /> 
      <EditItemStyle BackColor="#C0C000" Font-Size="XX-Large" /> 
      <Columns> 
          <asp:BoundColumn DataField="name" FooterText="Name" HeaderText="Фамилия"></asp:BoundColumn> 
          <asp:BoundColumn DataField="nationality" FooterText="Country" HeaderText="Страна"></asp:BoundColumn> 
          <asp:BoundColumn DataField="winningdate" FooterText="Year won" HeaderText="Год"></asp:BoundColumn> 
          <asp:BoundColumn DataField="work" FooterText="Work" HeaderText="Произведение"></asp:BoundColumn> 
          </Columns> 
          <FooterStyle Font-Bold="True" Font-Italic="False" Font-Overline="False" Font-Strikeout="False" Font-Underline="False" /> 
          <HeaderStyle Font-Bold="True" Font-Italic="False" Font-Overline="False" Font-Strikeout="False" Font-Underline="False" />  
  </asp:DataGrid> 
  

Добавим в эту форму с возможностью сортировки. DataGrid поддерживает свойство AllowSorting. Но это только потенциальная возможность сортировки, так как сам элемент сортировать не может, это должен обеспечить программист. При AllowSorting = True в заголовке выводятся гиперссылки, при нажатии на которые вызывается событие SortCommand. Так как нет автогенерации, в описание BoundColumn нужно вставить SortExpression.

      <asp:BoundColumn DataField="name" FooterText="Name" HeaderText="Фамилия" SortExpression="name"> 
      </asp:BoundColumn> 
  

Метод-обработчик события SortCommand принимает параметр типа DataGridSortCommandEventArgs, в свойстве SortExpression которого содержится строка - выражение сортировки SortExpression. Необходимо использовать это выражение для сортировки данных, полученных из источника данных.

  protected void DataGrid2_SortCommand(object source, DataGridSortCommandEventArgs e) 
  { 
      ViewState["sort"] = e.SortExpression; 
      bindData(); 
  } 
  

Где bindData() вынесен в отдельную функцию и вызывается также из Page_Load.

  private void bindData() 
  { 
      String xmlFilename = Server.MapPath("") + "\\nobel.xml"; 
      DataSet newDataSet = new DataSet(); 
      newDataSet.ReadXml(xmlFilename); 
      if (ViewState["sort"] != null) 
          newDataSet.Tables[3].DefaultView.Sort = (string)ViewState["sort"]; 
      DataTable newDataTable = newDataSet.Tables[3]; 
      DataGrid2.DataSource = newDataTable; 
      DataGrid2.DataBind(); 
  } 
  void Page_Load() 
  { 
      if (!IsPostBack) 
          bindData(); 
  } 
  

Фамилия

Страна

Год

Произведение

Romain Rollan

France

1915

"Jean-Cristophe"

George Bernard Shaw

Great Britain

1925

 

Boris Pasternak

Russia

1958

"Doctor Zhivago"

Gabriel Garsia Marquez

Columbia

1982

"100 years of solitude"

Name

Country

Year won

Work

DataGrid поддерживает возможность разбиения на страницы, но для этого тоже приходится писать код обработчиков событий. В WebMatrix имеются шаблоны таких страниц. С появлением GridView такую технику можно считать устаревшей, так как GridView позволяет делать все это с помощью одного только декларативного связывания.

Покажем возможность удаления, обновления и редактирования данных в DataGrid с помощью SqlDataSource.

Создайте на сервере SQL в базе DemoBase таблицу Users с 3 полями:

Column Name

Data Type

Allow Nulls

UID

int

 

Name

varchar(50)

 

Comments

varchar(250)

+

IsRegistered

bit

+

Поле UID - автоинкрементное. Поэтому операция INSERT не будет требовать задания его значения. Конечно, это первичный ключ. В таблице свойств найдите IdentitySpecification, раскройте его и выберите (IsIdentity).

Будем работать с таблицей с помощью 3 процедур.

  CREATE PROCEDURE dbo.SelectUsers 
  ( 
        @Col INT = 0 
  ) 
  AS 
  IF @Col = 0 
              SELECT * FROM Users 
        ELSE IF @Col = 1 
              SELECT * FROM Users ORDER BY NAME 
        RETURN  
  

Процедура EditUser будет использоваться для вставки записей, если @UID, и для обновления в противном случае.

  CREATE PROCEDURE dbo.EditUser 
        ( 
        @UID int = 0, 
        @Name varchar(50), 
        @Comments varchar(250), 
        @Registered bit 
  ) 
  AS 
        IF @UID = 0 
              INSERT INTO Users(Name, Comments, IsRegistered) VALUES(@Name, @Comments, @Registered) 
        ELSE 
              UPDATE Users SET Name = @Name, Comments = @Comments, IsRegistered = @Registered WHERE UID = @UID 
        RETURN 
  

Процедура для удаления записей.

  CREATE dbo.DeleteUser 
  ( 
        @UID int 
  )  
              AS 
              DELETE FROM Users WHERE UID = @UID 
        RETURN 
  

На форме будет находиться, кроме DataGrid, 2 элемента редактирования NameTextBox и CommentTextBox и кнопка Add. Для наших тайных целей добавим элемент управления типа HiddenField. Эта цель - хранит id текущего элемента и передавать его SqlDataSource.

Добавим на форму такой источник данных.

  <asp:SqlDataSource ID="SqlDataSource1" runat="server"  
      ConnectionString="<%$ ConnectionStrings:DemoBaseConnectionString %>" 
      SelectCommand="dbo.SelectUsers" SelectCommandType="StoredProcedure"  
      DeleteCommand="dbo.DeleteUser"  DeleteCommandType="StoredProcedure"  
      UpdateCommand="dbo.EditUser" UpdateCommandType="StoredProcedure"  
      InsertCommand="dbo.EditUser" InsertCommandType="StoredProcedure" 
      OldValuesParameterFormatString=""> 
      <InsertParameters> 
          <asp:Parameter Direction="ReturnValue" Name="RETURN_VALUE"  
              Type="Int32" /> 
          <asp:Parameter Name="UID" Type="Int32" DefaultValue="0" /> 
          <asp:ControlParameter Name="Name" Type="String" ControlID="NameTextBox"/> 
          <asp:ControlParameter Name="Comments" Type="String" ControlID="CommentTextBox" PropertyName="Text"/> 
          <asp:ControlParameter Name="Registered"  Type="Boolean" ControlID="Registered" PropertyName="Checked"/> 
      </InsertParameters> 
      <UpdateParameters> 
          <asp:Parameter Direction="ReturnValue" Name="RETURN_VALUE" 
            Type="Int32" /> 
          <asp:ControlParameter Name="UID" Type="Int32" ControlID="HiddenField1" /> 
          <asp:ControlParameter Name="Name" Type="String" ControlID="NameTextBox"/> 
          <asp:ControlParameter Name="Comments" Type="String" ControlID="CommentTextBox"/> 
          <asp:ControlParameter Name="Registered"  Type="Boolean" ControlID="Registered" PropertyName="Checked"/> 
      </UpdateParameters> 
      <DeleteParameters>  
          <asp:ControlParameter ControlID="HiddenField1"  
  PropertyName="Value" Name="UID" Type="Int32" />  
      </DeleteParameters>  
  </asp:SqlDataSource> 
  

Обратите внимание на то, что в InsertParameters значение параметра UID по умолчанию 0 и он не связан с элементом управления. В остальных случаях он связан с HiddenField1. Значение в это поле будет передаваться в обработчиках.

На этот раз DataGrid будет использовать шаблонизированные столбцы TemplateColumn. Этот тип столбца DataGrid позволяет полностью управлять форматом отображения и редактирования данных -можно выводить данные в несколько строк или использовать для редактирования данных любые элементы управления. Например, для отображения булевской информации используем элементы CheckBox.

  <asp:DataGrid id="UsersDataGrid"  runat="server"  
      AutoGenerateColumns="False" DataKeyField="UID"  
      OnDeleteCommand="UsersDataGrid_DeleteCommand"  
      OnUpdateCommand="UsersDataGrid_UpdateCommand"  
      OnEditCommand="UsersDataGrid_EditCommand" DataSourceID="SqlDataSource1" 
      AllowSorting="True" Caption="Users" CaptionAlign="Top">  
      <Columns> 
      <asp:TemplateColumn HeaderText= "Имя">  
        <ItemTemplate>  
          <asp:Label id="Label1" runat="server"  
          Text='<%#DataBinder.Eval(Container, "DataItem.Name")%>'> 
          </asp:Label> 
        </ItemTemplate>  
        <EditItemTemplate>  
          <asp:TextBox id=NameTextBox runat="server"  
          Text='<%# DataBinder.Eval(Container, "DataItem.Name") %>'> 
          </asp:TextBox> 
        </EditItemTemplate> 
      </asp:TemplateColumn>  
      <asp:TemplateColumn HeaderText="Комментарии"> 
        <ItemTemplate>  
          <asp:Label id="Label2" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.Comments")%>'></asp:Label> 
        </ItemTemplate> 
        <EditItemTemplate> 
          <asp:TextBox id= CommentTextBox runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.Comments")%>'> 
          </asp:TextBox> 
        </EditItemTemplate> 
      </asp:TemplateColumn> 
      <asp:TemplateColumn HeaderText= "Зарегистрирован"> 
        <ItemTemplate> 
          <asp:CheckBox  runat="server" ID="Registered" Checked='<%# (bool) DataBinder.Eval(Container, "DataItem.isRegistered") %>' 
                Enabled="False"></asp:CheckBox > 
        </ItemTemplate> 
        <EditItemTemplate> 
          <asp:CheckBox runat="server" ID="Registered" Checked='<%# (bool) DataBinder.Eval(Container, "DataItem.isRegistered") %>'></asp:CheckBox> 
        </EditItemTemplate> 
        </asp:TemplateColumn> 
      <asp:TemplateColumn> 
        <ItemTemplate> 
          <asp:LinkButton id="LinkButton1" runat="server" CommandName="edit">редактировать</asp:LinkButton> :: 
          <asp:LinkButton id="LinkButton2" runat="server" CommandName="delete">удалить</asp:LinkButton> 
        </ItemTemplate> 
        <EditItemTemplate> 
          <asp:LinkButton id="LinkButton3" runat="server" CommandName="update">принять</asp:LinkButton> :: 
          <asp:LinkButton id="LinkButton4" runat="server" CommandName="cancel">отменить</asp:LinkButton> 
        </EditItemTemplate> 
      </asp:TemplateColumn> 
    </Columns> 
  </asp:DataGrid> 
  

И остальные элементы:

  <asp:TextBox ID="NameTextBox" runat="server" ></asp:TextBox>  
  <asp:TextBox ID="CommentTextBox" runat="server"></asp:TextBox>  
  <asp:CheckBox ID="Registered" runat="server" /><br /><br /> 
  <asp:Button ID="Button1" runat="server" Text="Add" OnClick="Add_Click" /> 
  <asp:HiddenField ID="HiddenField1" runat="server" /> 
  

DataGrid уже будет выводить данные, имеет гиперссылки для правки и удаления, но при нажатии ничего не происходит. Остается написать нужный код. SqlDataSource уже знает параметры команды Delete, это единственный параметр, и связан он был с HiddenField1. Нужно записать значение ключа id в это поле.

  protected void UsersDataGrid_DeleteCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e) 
  { 
      HiddenField1.Value = UsersDataGrid.DataKeys[e.Item.ItemIndex].ToString(); 
      // Удаление 
      SqlDataSource1.Delete(); 
      // Обновление данных после удаления 
      UsersDataGrid.DataBind(); 
  } 
  

Добавление записи происходит еще проще, так как параметры процедуры Insert находятся в тех текстовых полях, которые заполняются для вставки:

  protected void Add_Click(object sender, EventArgs e) 
  { 
      SqlDataSource1.Insert(); 
      UsersDataGrid.DataBind(); 
  } 
  

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

  protected void UsersDataGrid_EditCommand(object source, DataGridCommandEventArgs e) 
  { 
      UsersDataGrid.EditItemIndex = e.Item.ItemIndex; 
      NameTextBox.Visible = false; 
      CommentTextBox.Visible = false; 
      Registered.Visible = false; 
      UsersDataGrid.DataBind(); 
  } 
  

Редактирование сложнее. В шаблоне столбцов элемента DataGrid указаны текстовые поля, которые появляются после нажания на ссылку «редактировать». Значения параметров надо брать оттуда, но их нельзя указать в декларации SqlDataSource, потому что они в момент генерации страницы их там просто нет. Например, для того, чтобы установить в режим редактирования строку DataGrid, необходимо присвоить свойству EditItemIndex элемента управления DataGrid значение индекса текущей строки.

В событии UpdateCommand в аргументе e находим текущую строку. Обновляемые данные находятся в TextBox-ах в ячейках 0 и 1. Чтобы выйти из режима редактирования, свойству EditItemIndex нужно присвоить значение -1.

  protected void UsersDataGrid_UpdateCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e) 
  { 
      TableCell cell=e.Item.Cells[0]; 
      TextBox cnt = (TextBox)cell.FindControl("NameTextBox"); 
      NameTextBox.Text = cnt.Text;  
      cell = e.Item.Cells[1]; 
      cnt = (TextBox)cell.FindControl("CommentTextBox"); 
      CommentTextBox.Text = cnt.Text; 
      HiddenField1.Value = UsersDataGrid.DataKeys[e.Item.ItemIndex].ToString(); 
      cell = e.Item.Cells[2]; 
      CheckBox check = (CheckBox)cell.FindControl("Registered"); 
      Registered.Checked = check.Checked; 
      SqlDataSource1.Update(); 
      UsersDataGrid.EditItemIndex = -1; 
      UsersDataGrid.DataBind(); 
      NameTextBox.Text = ""; 
      CommentTextBox.Text = ""; 
      NameTextBox.Visible = true; 
      CommentTextBox.Visible = true; 
      Registered.Visible = true; 
  } 
  

После обновления вновь читаем данные и делаем видимыми поля редактирования.

Отказ от редактирования без сохранения изменений обрабатывается в событии CancelCommand.

  protected void UsersDataGrid_CancelCommand(object source, DataGridCommandEventArgs e) 
  { 
      UsersDataGrid.EditItemIndex = -1; 
      NameTextBox.Visible = true; 
      CommentTextBox.Visible = true; 
      UsersDataGrid.DataBind(); 
  } 
  

Заключение

Мы рассмотрели 3 элемента управления, существовавшие с ASP.NET 1.0. Repeater использует только шаблоны, DataList создает таблицу и пользуется шаблоном для отображения ее строк, а DataGrid может обходиться и без шаблонов. Примерно такая же система существует и у новых элементов управления ASP.NET 2.0.

Объектная модель упрощает связывание с данными, но ее реальная мощь проявляется при использовании новых элементов управления GridView, DetailsView, FormView, которые мы рассмотрим в следующей лекции.

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 18.05.2007 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Microsoft Office 365 для Дома 32-bit/x64. 5 ПК/Mac + 5 Планшетов + 5 Телефонов. Подписка на 1 год.
Microsoft Office 365 Бизнес. Подписка на 1 рабочее место на 1 год
Microsoft 365 Business Standard (corporate)
Microsoft Office для дома и учебы 2019 (лицензия ESD)
Microsoft Windows Professional 10, Электронный ключ
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Новости ITShop.ru - ПО, книги, документация, курсы обучения
CASE-технологии
Программирование на Microsoft Access
Мир OLAP и Business Intelligence: новости, статьи, обзоры
Новости мира 3D-ускорителей
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100