Отображение сводной информации в нижнем колонтитуле элемента управления GridView (C#)

Скотт Митчелл

Загрузить PDF-файл

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

Введение

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

Эта задача ставит перед нами три задачи:

  1. Настройка GridView для отображения строки нижнего колонтитула
  2. Определение сводных данных; то есть, как мы вычислим среднюю цену или общее количество единиц на складе?
  3. Внедрение сводных данных в соответствующие ячейки строки нижнего колонтитула

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

Сводная информация отображается в строке нижнего колонтитула GridView

Рис. 1. Сводная информация отображается в строке нижнего колонтитула GridView (щелкните для просмотра полноразмерного изображения)

Это руководство, включающее категорию продуктов master/подробный интерфейс, основывается на концепциях, описанных в предыдущем руководстве Фильтрация основных и подробных данных с помощью DropDownList. Если вы еще не работали с предыдущим руководством, сделайте это, прежде чем продолжить работу с этим руководством.

Шаг 1. Добавление раскрывающегося списка категорий и элемента Products GridView

Прежде чем добавить сводную информацию в нижний колонтитул GridView, давайте просто создадим отчет master/подробностей. Завершив этот первый шаг, мы рассмотрим, как включить сводные данные.

Начните с открытия страницы SummaryDataInFooter.aspx в папке CustomFormatting . Добавьте элемент управления DropDownList и задайте для его ID значение Categories. Затем щелкните ссылку Выбрать источник данных из смарт-тега DropDownList и выберите добавление нового объекта ObjectDataSource с именем CategoriesDataSource , который вызывает CategoriesBLL метод класса GetCategories() .

Добавление нового объекта ObjectDataSource с именем CategoriesDataSource

Рис. 2. Добавление нового объекта ObjectDataSource с именем CategoriesDataSource (щелкните для просмотра полноразмерного изображения)

Вызов метода GetCategories() класса CategoriesBLL с помощью ObjectDataSource

Рис. 3. Вызов CategoriesBLL метода класса GetCategories() objectDataSource (щелкните, чтобы просмотреть полноразмерное изображение)

После настройки ObjectDataSource мастер возвращает нас в мастер настройки источника данных DropDownList, из которого необходимо указать, какое значение поля данных должно отображаться, а какое должно соответствовать значению DropDownList ListItem . CategoryName Отобразить поле и использовать в CategoryID качестве значения .

Используйте поля CategoryName и CategoryID в качестве текста и значения для ListItems соответственно

Рис. 4. Используйте CategoryName поля и CategoryID в Text качестве и Value для ListItem соответственно (щелкните, чтобы просмотреть полноразмерное изображение)

На этом этапе у нас есть DropDownList (Categories), который перечисляет категории в системе. Теперь необходимо добавить GridView, в который перечислены продукты, которые относятся к выбранной категории. Прежде чем это сделать, уделите немного времени, чтобы проверка флажок Включить AutoPostBack в смарт-теге DropDownList. Как описано в руководстве Фильтрация основных и подробных данных с помощью DropDownList, при задании свойства true DropDownList AutoPostBack на страницу будет возвращаться каждый раз при изменении значения DropDownList. Это приведет к обновлению GridView, отображая эти продукты для только что выбранной категории. AutoPostBack Если свойство имеет значение false (по умолчанию), изменение категории не приведет к обратной отправке и, следовательно, не обновит перечисленные продукты.

Установите флажок Включить autoPostBack в смарт-теге DropDownList.

Рис. 5. Установите флажок Enable AutoPostBack (Включить autoPostBack) в смарт-теге DropDownList (Щелкните для просмотра полноразмерного изображения)

Добавьте элемент управления GridView на страницу, чтобы отобразить продукты для выбранной категории. Задайте для GridView ID значение ProductsInCategory и привяжите его к новому объекту ObjectDataSource с именем ProductsInCategoryDataSource.

Добавление нового объекта ObjectDataSource с именем ProductsInCategoryDataSource

Рис. 6. Добавление нового объекта ObjectDataSource с именем ProductsInCategoryDataSource (щелкните для просмотра полноразмерного изображения)

Настройте ObjectDataSource таким образом, чтобы он вызвал ProductsBLL метод класса GetProductsByCategoryID(categoryID) .

Вызов метода GetProductsByCategoryID(categoryID) из ObjectDataSource

Рис. 7. Вызов GetProductsByCategoryID(categoryID) метода ObjectDataSource (щелкните для просмотра полноразмерного изображения)

GetProductsByCategoryID(categoryID) Так как метод принимает входной параметр, на последнем шаге мастера можно указать источник значения параметра. Чтобы отобразить эти продукты из выбранной категории, извлеките параметр из Раскрывающегося Categories списка.

Снимок экрана: окно

Рис. 8. Получение categoryID значения параметра из раскрывающегося списка "Выбранные категории" (щелкните для просмотра полноразмерного изображения)

После завершения работы мастера GridView будет иметь BoundField для каждого свойства продукта. Давайте очистим эти поля BoundField, чтобы отображались только ProductNameполя , UnitPrice, UnitsInStockи UnitsOnOrder BoundFields. Вы можете добавлять любые параметры уровня поля в оставшиеся поля BoundFields (например, форматирование в UnitPrice виде валюты). После внесения этих изменений декларативная разметка GridView должна выглядеть примерно так:

<asp:GridView ID="ProductsInCategory" runat="server"
    AutoGenerateColumns="False" DataKeyNames="ProductID"
    DataSourceID="ProductsInCategoryDataSource" EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="ProductName" HeaderText="Product"
          SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
            HeaderText="Price"
            HtmlEncode="False" SortExpression="UnitPrice">
            <ItemStyle HorizontalAlign="Right" />
        </asp:BoundField>
        <asp:BoundField DataField="UnitsInStock"
         HeaderText="Units In Stock" SortExpression="UnitsInStock">
            <ItemStyle HorizontalAlign="Right" />
        </asp:BoundField>
        <asp:BoundField DataField="UnitsOnOrder"
           HeaderText="Units On Order" SortExpression="UnitsOnOrder">
            <ItemStyle HorizontalAlign="Right" />
        </asp:BoundField>
    </Columns>
</asp:GridView>

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

Снимок экрана: отчет GridView для продуктов, относящихся к категории

Рис. 9. Получение categoryID значения параметра из раскрывающегося списка "Выбранные категории" (щелкните для просмотра полноразмерного изображения)

Элемент управления GridView может отображать строку верхнего и нижнего колонтитулов. Эти строки отображаются в зависимости от значений ShowHeader свойств и ShowFooter соответственно, с значениями ShowHeader по умолчанию true и ShowFooterfalse. Чтобы включить нижний колонтитул в GridView, просто присвойте его ShowFooter свойству значение true.

Задайте для свойства ShowFooter GridView значение true.

Рис. 10. Задайте свойству GridView ShowFooter значение true (щелкните, чтобы просмотреть полноразмерное изображение)

Строка нижнего колонтитула содержит ячейку для каждого из полей, определенных в GridView; однако эти ячейки по умолчанию пусты. Просмотрите ход работы в браузере. Если свойству ShowFooter теперь присвоено значение true, GridView включает пустую строку нижнего колонтитула.

GridView теперь включает строку нижнего колонтитула

Рис. 11. GridView теперь включает строку нижнего колонтитула (щелкните для просмотра полноразмерного изображения)

Строка нижнего колонтитула на рис. 11 не выделяется, так как она имеет белый фон. Давайте создадим FooterStyle класс CSS в Styles.css , который задает темно-красный фон, а затем настроим GridView.skin файл Skin в DataWebControls theme, чтобы назначить этот класс CSS свойству GridViewFooterStyleCssClass. Если вам нужно освежить скины и темы, вернитесь к руководству Отображение данных с помощью ObjectDataSource .

Начните с добавления следующего класса CSS в Styles.css:

.FooterStyle
{
    background-color: #a33;
    color: White;
    text-align: right;
}

Класс FooterStyle CSS по стилю похож на HeaderStyle класс , хотя HeaderStyleцвет фона немного темнее, а его текст отображается полужирным шрифтом. Кроме того, текст в нижнем колонтитуле выравнивается по правому краю, а текст верхнего колонтитула выравнивается по центру.

Затем, чтобы связать этот класс CSS с каждым нижним колонтитулов GridView, откройте GridView.skin файл в DataWebControls theme и задайте FooterStyleсвойство .CssClass После этого добавления разметка файла должна выглядеть следующим образом:

<asp:GridView runat="server" CssClass="DataWebControlStyle">
   <AlternatingRowStyle CssClass="AlternatingRowStyle" />
   <RowStyle CssClass="RowStyle" />
   <HeaderStyle CssClass="HeaderStyle" />
   <FooterStyle CssClass="FooterStyle" />
   <SelectedRowStyle CssClass="SelectedRowStyle" />
</asp:GridView>

Как показано на снимке экрана ниже, это изменение делает нижний колонтитул более четким.

Снимок экрана: сводные данные в строке нижнего колонтитула GridView с новым цветом фона.

Рис. 12. Строка нижнего колонтитула GridView теперь имеет красноватый цвет фона (щелкните для просмотра полноразмерного изображения)

Шаг 3. Вычисление сводных данных

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

  1. С помощью SQL-запроса мы можем отправить дополнительный запрос к базе данных для вычисления сводных данных для определенной категории. SQL включает ряд агрегатных функций, GROUP BY а также предложение для указания данных, по которым следует суммировать данные. Следующий SQL-запрос возвратит необходимые сведения:

    SELECT CategoryID, AVG(UnitPrice), SUM(UnitsInStock),
    SUM(UnitsOnOrder)
    FROM Products
    WHERE CategoryID = categoryID
    GROUP BY CategoryID
    

    Конечно, вы не хотите выполнять этот запрос непосредственно со SummaryDataInFooter.aspx страницы, а создайте метод в ProductsTableAdapter и ProductsBLL.

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

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

Создайте RowDataBound обработчик событий для GridView, выбрав GridView в Designer, щелкнув значок молнии в окно свойств и дважды щелкнув RowDataBound событие. При этом будет создан обработчик событий с именем ProductsInCategory_RowDataBound в SummaryDataInFooter.aspx классе кода программной части страницы.

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

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

  • _totalUnitPriceс типом decimal
  • _totalNonNullUnitPriceCountс типом int
  • _totalUnitsInStockс типом int
  • _totalUnitsOnOrderс типом int

Затем напишите код для увеличения этих трех переменных для каждой строки данных, обнаруженной в обработчике RowDataBound событий.

// Class-scope, running total variables...
decimal _totalUnitPrice = 0m;
int _totalNonNullUnitPriceCount = 0;
int _totalUnitsInStock = 0;
int _totalUnitsOnOrder = 0;
protected void ProductsInCategory_RowDataBound(object sender,
  GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // Reference the ProductsRow via the e.Row.DataItem property
        Northwind.ProductsRow product =
          (Northwind.ProductsRow)
          ((System.Data.DataRowView)e.Row.DataItem).Row;
        // Increment the running totals (if they are not NULL!)
        if (!product.IsUnitPriceNull())
        {
            _totalUnitPrice += product.UnitPrice;
            _totalNonNullUnitPriceCount++;
        }
        if (!product.IsUnitsInStockNull())
            _totalUnitsInStock += product.UnitsInStock;
        if (!product.IsUnitsOnOrderNull())
            _totalUnitsOnOrder += product.UnitsOnOrder;
    }
}

Обработчик RowDataBound событий начинается с того, что мы имеем дело с DataRow. После этого экземпляр, Northwind.ProductsRow который был привязан к объекту GridViewRow в , e.Row сохраняется в переменной product. Затем выполняющиеся переменные суммы увеличиваются на соответствующие значения текущего продукта (при условии, что они не содержат значения базы данных NULL ). Мы отслеживаем как общее число, UnitPrice так и количество записейNULLUnitPrice , не являющихся записями, так как средняя цена является коэффициентом этих двух чисел.

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

protected void ProductsInCategory_RowDataBound
    (object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
      ... Increment the running totals ...
    }
    else if (e.Row.RowType == DataControlRowType.Footer)
    {
      ... Display the summary data in the footer ...
    }
}

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

Чтобы отобразить текст в определенной ячейке нижнего колонтитула, используйте e.Row.Cells[index].Text = value, где Cells индексирование начинается с 0. Следующий код вычисляет среднюю цену (общую цену, делимую на количество продуктов) и отображает ее вместе с общим количеством единиц на складе и единиц в заказе в соответствующих ячейках нижнего колонтитула GridView.

protected void ProductsInCategory_RowDataBound
    (object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
      ... <i>Increment the running totals</i> ...
    }
    else if (e.Row.RowType == DataControlRowType.Footer)
    {
      // Determine the average UnitPrice
      decimal avgUnitPrice = _totalUnitPrice / (decimal) _totalNonNullUnitPriceCount;
      // Display the summary data in the appropriate cells
      e.Row.Cells[1].Text = "Avg.: " + avgUnitPrice.ToString("c");
      e.Row.Cells[2].Text = "Total: " + _totalUnitsInStock.ToString();
      e.Row.Cells[3].Text = "Total: " + _totalUnitsOnOrder.ToString();
    }
}

На рисунке 13 показан отчет после добавления этого кода. Обратите внимание, ToString("c") что приводит к тому, что сводная информация о средней цене форматируется как валюта.

Снимок экрана: сводные данные в строке нижнего колонтитула GridView, отформатированные в виде валюты.

Рис. 13. Строка нижнего колонтитула GridView теперь имеет красный цвет фона (щелкните для просмотра полноразмерного изображения)

Сводка

Отображение сводных данных является распространенным требованием отчета, и элемент управления GridView упрощает включение таких сведений в строку нижнего колонтитула. Строка нижнего колонтитула отображается, если свойству GridView ShowFooter присвоено значение true , и текст в ячейках может задаваться программным способом с помощью обработчика RowDataBound событий. Вычисление сводных данных можно выполнить путем повторного запроса к базе данных или с помощью кода в классе кода программной части страницы ASP.NET для программного вычисления сводных данных.

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

Счастливое программирование!

Об авторе

Скотт Митчелл (Scott Mitchell), автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с Веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 2.0 в 24 часа. Его можно связать по адресу mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.