Элемент управления GridView

167

GridView — исключительно гибкий табличный элемент управления, предназначенный для демонстрации данных в виде двумерной сетки (grid), или экранной таблицы, состоящей из строк и столбцов. Он включает в себя широкий диапазон встроенных средств, включая выделение, разбиение на страницы и редактирование. К тому же он может быть расширен с помощью шаблонов. Огромным преимуществом GridView перед DataGrid (ASP.NET 1.x) является его поддержка сценариев без кода. Используя GridView, можно без написания кода решать множество распространенных задач, таких как перемещение по страницам и выделение. В DataGrid для получения тех же средств нужно было кодировать обработку событий.

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

Определение столбцов

В продемонстрированных до сих пор примерах с GridView свойство AutoGenerateColumns устанавливалось в true. В этом случае GridView использует рефлексию для исследования объекта данных и нахождения полей (для записи) или свойств (для пользовательского объекта). Затем он создает столбцы для каждого из них в том порядке, в котором их обнаруживает.

Эта автоматическая генерация столбцов хороша для быстрого создания тестовых страниц, но не предоставляет необходимой гибкости, которая обычно требуется. Например, что если нужно скрыть столбцы, изменить порядок их следования или настроить некоторые аспекты их отображения, такие как форматирование и текст заголовков? Во всех подобных случаях понадобится установить AutoGenerateColumns в false и определить столбцы самостоятельно в разделе <Columns> дескриптора элемента управления GridView.

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

Типы столбцов GridView
Столбец Описание
BoundField

Этот столбец отображает текст поля источника данных

ButtonField

Этот столбец отображает кнопку для каждого значения в списке

CheckBoxField

Этот столбец отображает флажок для каждого элемента в списке. Используется автоматически для полей true/false (в SQL Server это поля, использующие битовый тип данных)

CommandField

Этот столбец предоставляет кнопки выделения или редактирования

HyperlinkField

Этот столбец отображает свое содержимое (поле из источника данных или статический текст) как гиперссылку

ImageField

Этот столбец отображает графические данные из двоичного поля (предполагая, что они могут быть успешно интерпретированы как поддерживаемый графический формат)

TemplateField

Этот столбец позволяет указывать множество полей, пользовательские элементы управления и произвольную HTML-разметку, используя специальный шаблон. Предоставляет наибольший контроль, но также требует максимум работы

Наиболее базовым типом столбца является BoundField, который привязывается к одному полю в объекте данных. Например, вот определение столбца с одиночной привязкой, отображающей поле EmployeelD:

<asp:BoundField DataField="EmployeeID" HeaderText="Id" />

Это предоставляет одно усовершенствование по сравнению со столбцом, сгенерированным автоматически, а именно — текст заголовка, который в данном случае изменен с "EmployeeID" на "Id".

Когда вы впервые создаете GridView, свойство AutoGenerateColumns не установлено (и потому используется значение по умолчанию true). После привязки его к элементу управления данными ничего не меняется. Однако если щелкнуть на ссылке Refresh Schema (Обновить схему) смарт-тега элемента управления источником данных, свойство AutoGenerateColumns переключается на false, и Visual Studio добавляет дескриптор <BoundField> к каждому полю, которое находит в источнике данных. Этот подход обладает рядом преимуществ:

Если источник данных изменен так, что он возвращает другой набор столбцов, можно повторно сгенерировать столбцы GridView. Просто выберите GridView и щелкните на ссылке Refresh Schema в смарт-теге. Это приведет к очистке всех пользовательских столбцов, которые были добавлены (такие как элементы управления редактированием).

Полное объявление GridView с явными столбцами и источником данных выглядит следующим образом:

<asp:SqlDataSource ID="getEmployeesSDS" runat="server"
             ConnectionString="<%$ ConnectionStrings:Northwind %>"
             SelectCommand="SELECT EmployeeID, FirstName, LastName, BirthDate, Title, City, Notes
                FROM Employees" />

<asp:GridView ID="GridView1" runat="server"
            DataSourceID="getEmployeesSDS" AutoGenerateColumns="False" DataKeyNames="EmployeeID">
            <Columns>
                <asp:BoundField DataField="EmployeeID" HeaderText="Id" />
                <asp:BoundField DataField="FirstName" HeaderText="FirstName" />
                <asp:BoundField DataField="LastName" HeaderText="LastName" />
                <asp:BoundField DataField="BirthDate" HeaderText="BirthDate" />
                <asp:BoundField DataField="Title" HeaderText="Title" />
                <asp:BoundField DataField="City" HeaderText="City" />
            </Columns>
</asp:GridView>

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

Свойства BoundField
Свойство Описание
DataField

Это свойство указывает имя поля (для таблицы базы данных) или свойства (для объекта) элемента данных, которое необходимо отобразить в данном столбце

DataFormatString

Это свойство форматирует поле. Удобно для задания правильного представления чисел и дат. Чтобы его использовать, в предыдущих версиях .NET необходимо было устанавливать свойство HtmlEncode в false. Теперь это уже не требуется

ApplyFormatInEditMode

Если равно true, то строка формата будет использоваться для форматирования значения, даже если оно отображается в текстовом поле в режиме редактирования. По умолчанию равно false, что означает применение лежащего в основе обычного формата (т.е., например, 1143.02 вместо $1,142.02)

HeaderText, FooterText и HeaderImageUrl

Первые два свойства устанавливают текст заголовка и нижнего колонтитула сетки, если сетка имеет заголовок (ShowHeader установлено в true) и нижний колонтитул (ShowFooter установлено в true). Заголовок чаще всего используется для указания описательного имени, такого как имя поля, в то время как нижний колонтитул может содержать динамически вычисляемое значение вроде суммы по столбцу. Чтобы показать графическое изображение в заголовке вместо текста, понадобится установить свойство HeaderImageUrl

Readonly

Если равно true, то значение столбца не может быть изменено в режиме редактирования. Никакого редактирующего элемента управления не предоставляется. Часто объявляются как Readonly поля первичного ключа

InsertVisible

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

Visible

Если равно false, столбец не будет видимым на странице (и никакой HTML-разметки для него не генерируется). Это свойство предоставляет удобный способ программного сокрытия и показа определенных столбцов, изменения общего представления данных

SortExpression

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

HtmlEncode

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

NullDisplayText

Это свойство определяет текст, который будет отображен для null-значения. По умолчанию равно пустой строке, хотя это можно изменить на жестко закодированное значение, такое как (not specified)

ConvertEmptyStringToNull

Если равно true, то перед фиксацией редактирования все пустые строки будут преобразованы в null-значения

ControlStyle, HeaderStyle, FooterStyle и ItemStyle

Эти свойства конфигурируют внешний вид только данного столбца, переопределяя стили строки

Теперь, когда известны основы GridView, можно приступать к исследованию его высокоуровневых свойств. В последующих разделах рассматриваются следующие темы:

Форматирование в GridView

Форматирование состоит из нескольких взаимосвязанных задач. Первым делом нужно гарантировать, что даты, валюты и другие числовые значения будут представлены соответствующим способом. Эта работа выполняется свойством DataFormatString. Далее необходимо применить смесь цветов, шрифтов, рамок и опций выравнивания к каждому аспекту экранной сетки — от заголовка до элементов данных. GridView поддерживает все эти средства через стили. И, наконец, можно перехватывать события, просматривать данные строк и программно применять форматирование к определенным элементам данных. Все эти приемы рассматриваются в последующих разделах.

Сам по себе GridView также предлагает несколько свойств форматирования, которые самоочевидны и потому здесь не раскрываются. К ним относятся GridLines (для добавления и сокрытия рамок сетки), CellPadding и CellSpacing (для управления общими промежутками между ячейками), а также Caption и CaptionAlign (для добавления заголовка в верхней части сетки).

Хотите создать прокручиваемый GridView внутри веб-страницы? Это сделать легко. Просто поместите GridView внутрь элемента управления Panel, установите соответствующий размер панели, а свойство Panel.Scrollbars — в Auto, Vertical или Both.

Форматирование полей

Каждый столбец BoundField предоставляет свойство DataFormatString, которое можно использовать для настройки внешнего вида чисел и дат, используя форматную строку. Форматные строки обычно состоят из заполнителя и индикатора формата, которые заключены в фигурные скобки. Типичная форматная строка выглядит примерно так:

{0:C}

Здесь 0 представляет собой значение, которое будет отформатировано, а буква — предопределенный стиль формата. Буква C означает денежный формат, основанный на установках культуры, касающихся текущего потока. По умолчанию компьютер, настроенный для региона English (United States) работает с локалью en-US и отображает денежные значения с символом доллара (поэтому 3400.34 превращается в $3,400.34). Компьютер, сконфигурированный с локалью ru-RU (Россия) отобразит 3,400.34 руб.

Все сведения о форматах, которые можно использовать, вы найдете в статье «Форматирующие строки». Ниже показан столбец, использующий форматную строку для даты:

<asp:BoundField DataField="BirthDate" HeaderText="BirthDate" DataFormatString="{0:d}" />

Стили

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

Стили GridView
Описание Стиль
HeaderStyle

Конфигурирует внешний вид строки заголовка, содержащей заголовки столбцов, если включено их отображение (т.е. ShowHeader установлено в true)

RowStyle

Конфигурирует внешний вид каждой строки данных

AlternatingRowStyle

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

SelectedRowStyle

Конфигурирует внешний вид текущей выбранной строки

EditRowStyle

Конфигурирует внешний вид строки, находящейся в режиме редактирования

EmptyDataRowStyle

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

FooterStyle

Конфигурирует внешний вид строки нижнего колонтитула GridView, если включено его отображение (т.е. ShowFooter установлено в true)

PagerStyle

Конфигурирует внешний вид строки со ссылками на страницы, если включено постраничное разбиение (т.е. AllowPaging установлено в true)

Стили — это не простые однозначные свойства. Каждый стиль предоставляет объект Style, включающий свойства для выбора цветов (ForeColor и BackColor), добавления рамок (BorderColor, BorderStyle и BorderWidth), установки размеров строки (Height и Width), указания выравнивания строки (HorizontalAlign и Vertical Align), а также конфигурирования внешнего вида текста (Font и Wrap). Эти свойства стиля дают возможность уточнить почти каждый аспект внешнего вида элемента. И если вы не хотите жестко кодировать все настройки внешнего вида веб-страницы, то можете просто установить свойство CssClass объекта стиля в класс связанной таблицы стилей CSS.

При установке свойств стиля можно использовать два похожих синтаксиса. Первый из них — синтаксис обхода объекта для указания расширенных свойств стиля как атрибутов дескриптора. Вот пример:

<asp:GridView ID="GridView1" runat="server" HeaderStyle-ForeColor="Blue"
            ...>
	...
</asp:GridView>

В качестве альтернативы можно добавить вложенные дескрипторы, как показано ниже:

<asp:GridView ID="GridView1" runat="server" ...>
	<HeaderStyle ForeColor="Blue" ... />
    ...
</asp:GridView>

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

Этот прием часто используется для определения специальной ширины столбца. Если для столбца не указана специальная ширина, ASP.NET устанавливает такую ширину каждого столбца, чтобы поместились содержащиеся в нем данные (или, если разрешен перенос строк, то чтобы уместить текст без разрыва слов между строками). Если значения отличаются друг от друга размерами, ширина определяется по самому большому значению либо по длине заголовка столбца — в зависимости от того, что окажется больше. Однако если сетка достаточно широка, столбец можно расширить так, чтобы он не был прижат к соседним столбцам. В этом случае понадобится явно задать большую ширину.

Вот как выглядит полностью форматированный дескриптор GridView:

<html>
<head runat="server">
    <title>Основы ASP.NET</title>
    <style>
        .Header th, .Row td {
            padding: 10px;
        }
    </style>
</head>
<body>    
    <form id="form1" runat="server">
        <asp:SqlDataSource ID="getEmployeesSDS" runat="server"
             ConnectionString="<%$ ConnectionStrings:Northwind %>"
             SelectCommand="SELECT EmployeeID, FirstName, LastName, BirthDate, Title, City, Notes
                FROM Employees" />

        <asp:GridView ID="GridView1" runat="server"
            DataSourceID="getEmployeesSDS" DataKeyNames="EmployeeID" AutoGenerateColumns="False"
            Font-Names="Trebuchet MS" Font-Size="Small" ForeColor="#333333" GridLines="None"
            RowStyle-CssClass="Row">

            <FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
            <RowStyle BackColor="#FFFBD6" ForeColor="#333333" />
            <PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" />
            <SelectedRowStyle BackColor="#FFCC66" Font-Bold="True" ForeColor="Navy" />
            <HeaderStyle BackColor="#28a4fb" Font-Bold="True" ForeColor="White" CssClass="Header" />
            <AlternatingRowStyle BackColor="White" />

            <Columns>
                <asp:BoundField DataField="EmployeeID" HeaderText="ID" InsertVisible="False"
                    ReadOnly="True">
                    <ItemStyle Font-Bold="True" BorderWidth="1" />
                </asp:BoundField>
                <asp:BoundField DataField="FirstName" HeaderText="FirstName" />
                <asp:BoundField DataField="LastName" HeaderText="LastName" />
                <asp:BoundField DataField="BirthDate" HeaderText="BirthDate" DataFormatString="{0:MM/dd/yyyy}">
                    <ItemStyle BackColor="LightSteelBlue" />
                </asp:BoundField>
                <asp:BoundField DataField="Title" HeaderText="Title" />
                <asp:BoundField DataField="Notes" HeaderText="Notes">
                    <ItemStyle Wrap="True" Width="400" />
                </asp:BoundField>
            </Columns>

        </asp:GridView>
    </form>
</body>
</html>

В примере применяются свойства GridView для установки шрифта и выравнивания расстояния между столбцами и линиями сетки. Используются стили для выделения заголовков полужирным и настраивается фон основных и дополнительных столбцов. Вдобавок специфичные для столбца настройки стиля выделяют другим цветом фона информацию о дате рождения, выделяют полужирным значения идентификаторов, используют CSS-стили и явно устанавливают размер столбца Notes. Строка DataFormatString используется для форматирования всех значений дат в поле BirthDate. Ниже показан конечный результат:

Сформатированный GridView

Настройка стилей в Visual Studio

Кодировать свойства стиля вручную в дескрипторе элемента управления GridView не обязательно, поскольку этот элемент предоставляет развитую поддержку во время проектирования. Чтобы установить свойства стиля, можно перейти в окно Properties (Свойства) и модифицировать в нем эти свойства. Например, для установки шрифта заголовка раскройте свойство HeaderStyle, чтобы отобразить вложенное свойство Font, и установите его.

Единственное ограничение этого подхода состоит в том, что он не позволяет устанавливать стили отдельных столбцов. Если это необходимо, откройте диалоговое окно Fields за счет редактирования свойства Columns. Затем выберите в нем соответствующий столбец и должным образом установите его свойства стиля.

Можно даже установить комбинацию стилей с использованием предопределенной темы, щелкнув на ссылке AutoFormat (Автоформат) в смарт-теге GridView. На рисунке ниже показано диалоговое окно AutoFormat (Автоформат) с предустановленными стилями, доступными для выбора. Чтобы очистить все установки стиля, выберите элемент Remove Formatting (Удалить форматирование):

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

Значения, специфичные для форматирования

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

Решение состоит в реагировании на событие GridView.RowDataBound. Это событие генерируется, когда создается часть сетки (заголовок, нижний колонтитул, номер страницы либо нормальный, дополнительный или выделенный элемент). К текущей строке при этом можно получить доступ как к элементу управления GridViewRow. Свойство GridViewRow.DataItem представляет объект данных заданной строки, а коллекция GridViewRow.Cells позволяет извлечь содержимое строки. GridViewRow можно использовать для изменения цветов и выравнивания, добавления и удаления дочерних элементов управления и т.п.

В следующем примере обрабатывается событие RowDataBound и устанавливаются цвета в соответствии с определенными правилами:

Ниже приведен полный код обработчика события RowDataBound, реализующего упомянутые правила:

protected void gridEmployees_RowDataBound(object sender, GridViewRowEventArgs e)
{
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            // Получить дату рождения
            DateTime birthDate = (DateTime)DataBinder.Eval(e.Row.DataItem, "BirthDate");

            // Форматирование строк на основе даты рождения сотрудника
            if (birthDate.Year <= 1955)
            {
                e.Row.BackColor = System.Drawing.Color.LightPink;
                e.Row.ForeColor = System.Drawing.Color.Maroon;
            }
            else if (birthDate.Year > 1955 && birthDate.Year <= 1960)
            {
                e.Row.BackColor = System.Drawing.Color.LightCyan;
                e.Row.ForeColor = System.Drawing.Color.DarkBlue;
            }
            else
            {
                e.Row.BackColor = System.Drawing.Color.LimeGreen;
                e.Row.ForeColor = System.Drawing.Color.White;
            }
        }
}

Сначала производится проверка, что создаваемый элемент является строкой данных (а не каким-то другим интерфейсным элементом вроде номера страницы, нижнего колонтитула или заголовка). Если элемент имеет правильный тип, из элемента привязанных данных извлекается значение поля BirthDate, которое сравнивается с датами. На рисунке ниже показана результирующая страница:

Форматирование индивидуальных строк на основе значений

В этом примере используется метод DataBinder.Eval() для извлечения части информации из элемента данных с помощью рефлексии. В качестве альтернативы можно было бы привести e.Row.DataItem к корректному типу (такому как EmployeeDetails для ObjectDataSource), DataRowView (для SqlDataSource в режиме DataSet) или DbDataRecord (для SqlDataSource в режиме DataReader). Тем не менее, подход DataBinder.Eval() работает во всех этих сценариях (ценой некоторого замедления).

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

Пройди тесты
Лучший чат для C# программистов