Обзор GridView

Что такое GridView


С точки зрения функциональности – это такая же таблица, как и DataGrid, каждая запись которой соответствует записи в источнике данных. Каждый столбец может быть ассоциирован с полем в источнике данных. Помимо этого, GridView (как и DataGrid) имеет шапку (Header), нижний колонтитул (Footer) и информацию о разбивке на страницы (Pager).

GridView обявлен как:

[ControlValuePropertyAttribute("SelectedValue")]
  public class
GridView : CompositeDataBoundControl, IPostBackContainer, IPostBackEventHandler, ICallbackContainer,
         
ICallbackEventHandler

CompositeDataBoundControl – это базовый класс, который обеспечивает связывание с данными (данный класс в свою очередь наследует DataBoundControl который является базовым для всех data-bound контролов в ASP.NET 2.0.

IPostBackContainer и IPostBackEventHandler необходимы для обработки всех PostBack’ов контрола, а реализация интерфейсов ICallbackContainer и ICallbackEventHandler позволяет задействовать новый механизм клиентских асинхронных вызовов.

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

Эта модель представляет собой схему, когда между самим источником данных и слоем вывода данных (в нашем случае это GridView) находится еще один слой, который является посредником между источником и контролом визуализации данных и который предоставляет общий интерфейс как для первого (источника данных), так и для вторых (контролов визуализации, будь то наш GridView или допустим FormView). Для примера рассмотрим один из основных контролов визуализации – SqlDataSource. Как видно из названия, данный контрол предназначен для работы с SQL. Прежде всего, мы должны поместить этот контрол на форму (в любое место формы между тегами <form runat=”server”> и </form>):

<asp:SqlDataSource ID="SqlDataSource1" runat="server"></asp:SqlDataSource>

Этот контрол имеет 4 основных свойства, по названиям которых можно догадаться об их предназначении – SelectCommand, InsertCommand, UpdateCommand и DeleteCommand. На том, как передавать в эти sql-команды параметры, я останавливаться не буду – это достойно отдельной статьи; для нас сейчас важно то, что эти свойства описывают sql-команды для каждого из 4-х действий над данными.

<asp:SqlDataSource ID="SqlDataSource1" runat="server"
 
ConnectionString="<%$ ConnectionStrings: MyConnectionString %>"
       
SelectCommand="SELECT * FROM CartProducts"
       
InsertCommand="INSERT INTO CartProducts(id_cat, [name], price) VALUES(@id_cat, @name, @price)"
       
UpdateCommand="UPDATE CartProducts SET id_cat=@id_cat, [name]=@name, price=@price WHERE [id]=@id"
       
DeleteCommand="DELETE FROM CartProducts WHERE [id]=@id">
        <
DeleteParameters>
            <
asp:Parameter Name="id" Type="Int32" />
  </
DeleteParameters>
  </
asp:SqlDataSource>

Выборка, добавление, обновление и удаление данных.


Прежде всего, нам необходимо связать наш GridView с контролом-источником. Для этого у GridView есть свойство DataSourceID, значение которого должно соответствовать ID контрола-источника. Хочу обратить внимание на то, что GridView имеет также свойство DataSource, которое служит для связывания данных «по старинке» - в коде с присваиванием объекта типа IList. Использование обоих свойств одновременно приведет к ошибке – необходимо использовать либо DataSource, либо DataSourceID.

Итак, мы связали DataSource с контролом-источником данных. Если свойство SelectCommand (для объекта ObjectDataSource это SelectMethod) установлено – с GridView будут связаны данные, полученные в результате выполнения этой команды (или метода в случае с ObjectDataSource).

<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" AutoGenerateColumns="false">
      <
Columns>
          <
asp:BoundField HeaderText="Name" DataField="name" />
          <
asp:BoundField HeaderText="Price" DataField="price" />
      </
Columns>
  </
asp:GridView>

Если мы сейчас откроем нашу страницу – мы увидим что-то вроде:

Обзор GridView

Далее займемся удалением строк (и записей из источника данных). Как мы видим, DeleteCommand принимает параметр типа int, который называется id и соответствует id записи в таблице. Мы знаем, что id является уникальным полем и поэтому с чистой совестью делаем это поле ключевым для нашего GridView:

<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" DataKeyNames="id" AutoGenerateColumns="false">
      <
Columns>
          <
asp:BoundField HeaderText="Name" DataField="name" />
          <
asp:BoundField HeaderText="Price" DataField="price" />
      </
Columns>
  </
asp:GridView>

Далее нам необходимо добавить кнопку для каждой строки, которая будет удалять строку из GridView и из источника данных. Проще всего это сделать, добавив новый столбец типа CommandField:

<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" DataKeyNames="id" AutoGenerateColumns="false">
      <
Columns>
          <
asp:BoundField HeaderText="Name" DataField="name" />
          <
asp:BoundField HeaderText="Price" DataField="price" />
          <
asp:CommandField ShowDeleteButton="true" />
      </
Columns>
  </
asp:GridView>

Пробуем нашу страницу в действии:

Обзор GridView

Отлично. Теперь более сложное действие – редактирование. Для редактирования необходимо перевести необходимую нам строку в состояние редактирования. Для этого в нашем (или в новом, это кто как хочет) столбце CommandField добавляем ShowEditButton="true"

<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" DataKeyNames="id" AutoGenerateColumns="false">
      <
Columns>
          <
asp:BoundField HeaderText="Name" DataField="name" />
          <
asp:BoundField HeaderText="Price" DataField="price" />
          <
asp:CommandField ShowDeleteButton="true" ShowEditButton="true"/>
      </
Columns>
  </
asp:GridView>

Посмотрим, что у нас получается:

Обзор GridView

Как мы видим, строка переводится в режим редактирования и для каждого BoundField вместо обычного текста появляется текстовое поле. Но если мы посмотрим на наш UpdateCommand, то увидим, что помимо Name и Price мы должны еще передать id_cat (ID категории, к которой принадлежит товар). Проще всего это можно сделать добавив еще один BoundField, который будет связывать данный столбец с полем id_cat из таблицы, а в состоянии редактирования будет отображать TextBox. Но менять категорию, указывая ее id, соответствующее id в таблице – не лучший вариант, гораздо лучше было бы отразить в DropDownList. Прежде всего мы добавим новый столбец типа TemplateField, и для этого столбца определим ItemTemplate и EditItemTemplate как показано ниже:

<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" DataKeyNames="id" AutoGenerateColumns="false">
      <
Columns>
          <
asp:TemplateField>
              <
EditItemTemplate>
                  <
asp:DropDownList runat="server" ID="ddlCategories"></asp:DropDownList>
              </
EditItemTemplate>
              <
ItemTemplate>
                  <
asp:Label runat="server" ID="lblCategory"></asp:Label>
              </
ItemTemplate>
          </
asp:TemplateField>
          <
asp:BoundField HeaderText="Name" DataField="name" />
          <
asp:BoundField HeaderText="Price" DataField="price" />
          <
asp:CommandField ShowDeleteButton="true" ShowEditButton="true"/>
      </
Columns>
  </
asp:GridView>

Теперь при переходе строки в состояние редактирования вместо TextBox будет показан DropDownList. Далее нам необходимо связать этот DropDownList со списком из таблицы Categories. Хочу сообщить, что в ASP.NET 2.0 множество контролов получило возможность работать с объектной моделью источников данных, в том числе и DropDownList. Поэтому добавляем еще один SqlDataSource на форму, устанавливаем ему SelectCommand-=”SELECT * FROM Categories”, далее устанавливаем свойство нашего DropDownList DataSourceID=”SqlDataSource2”.

<asp:SqlDataSource ID="SqlDataSource2" runat="server"
      
ConnectionString="<%$ ConnectionStrings: MyConnectionString %>"
      
SelectCommand="SELECT * FROM CartProducts">
  </
asp:SqlDataSource>
  <
asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" DataKeyNames="id" AutoGenerateColumns="false">
      <
Columns>
          <
asp:TemplateField HeaderText="Category">
              <
EditItemTemplate>
                  <
asp:DropDownList runat="server" ID="ddlCategories" DataSourceID="SqlDataSource2" DataTextField="category" DataValueField="id" SelectedValue='<%# Bind("id_cat") %>'></asp:DropDownList>
              </
EditItemTemplate>
              <
ItemTemplate>
                  <
asp:Label runat="server" ID="lblCategory"></asp:Label>
              </
ItemTemplate>
          </
asp:TemplateField>
          <
asp:BoundField HeaderText="Name" DataField="name" />
          <
asp:BoundField HeaderText="Price" DataField="price" />
          <
asp:CommandField ShowDeleteButton="true" ShowEditButton="true"/>
      </
Columns>
  </
asp:GridView>

Обзор GridView

Редактирование работает, но в состоянии отображения строки нам необходимо вывести название категории. Для этого нам нужно по значению id_cat получить название. Хоть и эту задачу при желании можно решить декларативно, напишем пару строчек кода J

Прежде всего обработаем событие RowDataBound – аналог события ItemDataBound в DataGrid.

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
  {
  }

GridViewRow имеет свойства RowState и RowType, которые имеют типы перечислений DataControlRowState и DataControlRowType соответственно. Как нетрудно догадаться – первое из них хранит текущее состояние строки (например, строка в состоянии редактирования), а второе – тип строки (например, что данная строка является заголовком). Для того, чтобы выбрать все «нормальные» строки и только в режиме отображения, можно использовать следующую проверку:

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
  {
     if (
e.Row.RowType == DataControlRowType.DataRow &&
     (
e.Row.RowState == DataControlRowState.Normal || e.Row.RowState == DataControlRowState.Alternate))
      {
 
// устанавливаем необходимое значение для lblCategory            ((Label)e.Row.FindControl("lblCategory")).Text = …
      
}
  }

В GridView все нечетные строки считаются «нормальными», а все нечетные – альтернативными, поэтому RowState проверяется на 2 значения. Используя помимо декларативного программирования «обычное» программирование в коде страницы можно реализовать в GridView довольно сложную логику.

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

GridView не имеет стандартных средств для вставки новых записей. Для этого удобно использовать FormView и DetailView. Если же очень хочется реализовать вставку в GridView – можно создать форму в PagerTemplate.

Обратите внимание, что контрол SqlDataSource имеет свойство InsertCommand.
GridView и Visual Studio.NET 2005.

Все операции, которые мы проделали со страницей с GridView, можно проделывать и в режиме дизайнера Visual Studio.NET 2005. Скажу, что в Visual Studio.NET 2005 появилась новая возможность, называемая smart tags, которая представляет собой всплывающие окошка с настройками того или иного компонента. Главные особенности этой возможности – удобство в использовании и легкость создания smart tags для своих собственных компонентов. О том, как создавать smart tags, вы можете прочитать в статье в журнале MSDN Magazine за июль 2005 г. Статья называется: “Smart tags. Simplify UI Development With Custom Designer Actions In Visual Studio”, автор статьи: Michael Weinhardt. Итак, перведем нашу страницу в режим Design и и на GridView нажмем в правом верхнем углу на треугольную стрелку. Справа от контрола появится всплывающее окно:

Обзор GridView

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

ованным парамет возможность сконфигурировать сам DataSource. Раздел Columns также позволяет в еще одном дополнительном окошке сконфигурировать столбцы как нам необходимо – для каждого типа столбцов справа имеется полный перечень его свойств, а ссылка “Convert this field into a Template Column” позволяет перевести тот или иной столбец в аналогичный по функциональности, но типа TemplateField. Далее в TemplateField мы можем задать новые «значения» для разных режимов столбца, например установить DropDownList вместо TextBox для режима редактирования, как нам это требовалось выше.

Обзор GridView

Помимо новой концепции связи с источником данных, GridView по сравнению с DataGrid имеет несколько не столь существенных, но все же приятных нововведений.
EmptyDataTemplate

В DataGrid eсли источник не имеет ни одной записи – то чтобы вывести сообщение вроде «Нет записей» приходилось делать такой финт – добавлять любой контрол, который выводит текст (например, Label) и при биндинге проверять количество записей в источнике и если это количество было 0 – то прятать DataGrid, а в Label выводить надпись. Причем нужно было также не забыть «обнулять» эту строку каждый раз при биндинге, т.к. в противном случае надпись бы оставалась, даже если данные уже появились. В GridView введен новый шаблон EmptyDataTemplate:

<asp:GridView ID="GridView1" runat="server">
  <
EmptyDataTemplate>
            
No records
 
</EmptyDataTemplate>
  </
asp:GridView>

Эта надпись будет выведена только в случае, если источник не имеет ни одной записи, иначе этот блок игнорируется.
«Парные» события.

В ASP.NET 2.0 практически все контролы (и GridView в их числе) имеют по два события для каждого «физического» события. Одно из них возникает до начала выполнения операции, второе – после. Например, RowDeleting и RowDeleted – в RowDeleting мы можем узнать что будет удаляться.
Применение обратных вызовов страницы из javascript сценариев.

Свойство EnablePagingAndSortingCallbacks (по умолчанию false) позволяет применять технологию обратных вызовов страницы (это также нововведение в ASP.NET 2.0) для перехода между страницами и сортировки данных. Напомню, что данная технология позволяет не перегружать всю страницу, а как бы перегрузить только сам контрол.
Адаптация GridView для мобильных устройств.

ASP.NET 2.0 позволяет программисту адаптировать GridView для генерации HTML, более «дружественного» для мобильных устройств. Наиболее яркое отличие мобильных устройств от ПК – это меньший экран. Для вывода только одной записи и механизма навигации между ними существует группа элементов SummaryTitle, DetailLink, DetailTitle и свойство SummaryViewColumn.
Разбивка на страницы.

Прежде всего хочу сказать, что SqlDataSource позволяет оптимизировать запрос к БД и выбирать только данные, необходимые для текущей страницы GridView (допустим, если в GridView стоит PageSize=20, то SqlDataSource выберет только 20 записей из тех нескольких тысяч, что есть в таблице). И хотя это больше заслуга SqlDataSource, чем GridView – результат этого сказывается на GridView J Также класс PagerSettings (класс для работы с paging) имеет новые предопределенные кнопки – первая и последняя страницы. Кроме всего прочего, вместо текста можно использовать картинки.
Новые типы столбцов.

Для GridView введены некоторые новые типы столбцов: CheckBoxField и ImageField, по названиям которых несложно догадаться что они из себя представляют J
Локализация GridView.

Данный абзац не является нововведением в GridView и не является собственно локализацией именно этого контрола, но хочу сказать об этом пару слов. По умолчанию все надписи в GridView выводятся на английском языке. Можно сделать локализацию стандартным способом – созданием файла ресурсов со всеми соответствующими надписями, а потом заменой всех надписей на надписи из файла ресурсов и т.д., а можно сделать одним махом – установкой соответствующего Language Pack и указанием локали в web.config. Например, для локализации GridView на русский язык можно скачать .NET 2.0 Framework Russian Laguage Pack ( http://www.microsoft.co.ke/downloads/details.aspx?familyid=39C8B63B-F64B-4B68-A774-B64ED0C32AE7&displaylang=en ) и установкой

<globalization culture="ru-RU" uiCulture="ru-RU" />

В web.config. Как побочный эффект локализируются также все остальные контролы, а также все системные сообщения относительно этого сайта (например, сообщения об ошибках) выводятся на русском языке.

Автор: Oleg Shastitko