Добавление столбца GridView переключателей (C#)

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

Скачивание примера приложения или Загрузка PDF-файла

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

Введение

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

Это руководство и следующее основное внимание уделяется улучшению процесса выбора строк. Как было рассмотрено в образце/подробностях с помощью выбираемого элемента управления GridView с подробными сведениями DetailView, мы можем добавить в GridView элемент CommandField, включающий кнопку SELECT. При нажатии происходит обратная передача, и свойство SelectedIndex GridView s обновляется до индекса строки, для которой была нажата кнопка выбора. В базе данных "основной/подробности" с помощью доступного для выбора главного элемента управления GridView с руководством по DetailView мы увидели, как использовать эту функцию для отображения сведений о выбранной строке GridView.

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

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

Шаг 1. Создание усовершенствованных веб-страниц GridView

Прежде чем начать улучшать элемент управления GridView для включения столбца переключателей, давайте сначала создадим страницы ASP.NET в нашем проекте веб-сайта, которые понадобятся для работы с этим руководством и следующих двух. Для начала добавьте новую папку с именем EnhancedGridView. Затем добавьте в эту папку следующие страницы ASP.NET, чтобы связать каждую страницу с главной страницей Site.master:

  • Default.aspx
  • RadioButtonField.aspx
  • CheckBoxField.aspx
  • InsertThroughFooter.aspx

Добавление страниц ASP.NET для учебников, связанных с SqlDataSource

Рис. 1. добавление страниц ASP.NET для учебников, связанных с SqlDataSource

Как и в других папках, Default.aspx в папке EnhancedGridView будут перечислены учебники в разделе. Вспомним, что SectionLevelTutorialListing.ascx пользовательский элемент управления предоставляет эти функции. Таким образом, добавьте этот пользовательский элемент управления в Default.aspx, перетащив его из обозреватель решений на страницу s представление конструирования.

добавить пользовательский элемент управления SectionLevelTutorialListing. ascx в Default. aspx

Рис. 2. Добавление пользовательского элемента управления SectionLevelTutorialListing.ascx в Default.aspx (щелкните, чтобы просмотреть изображение с полным размером)

Наконец, добавьте эти четыре страницы в качестве записей в файл Web.sitemap. В частности, добавьте следующую разметку после использования <siteMapNode>элемента управления SqlDataSource:

<siteMapNode 
    title="Enhancing the GridView" 
    url="~/EnhancedGridView/Default.aspx" 
    description="Augment the user experience of the GridView control.">
    <siteMapNode 
        url="~/EnhancedGridView/RadioButtonField.aspx" 
        title="Selection via a Radio Button Column" 
        description="Explore how to add a column of radio buttons in the GridView." />
    <siteMapNode 
        url="~/EnhancedGridView/CheckBoxField.aspx" 
        title="Selection via a Checkbox Column" 
        description="Select multiple records in the GridView by using a column of 
            checkboxes." />
    <siteMapNode 
        url="~/EnhancedGridView/InsertThroughFooter.aspx" 
        title="Add New Records through the Footer" 
        description="Learn how to allow users to add new records through the 
            GridView's footer." />
</siteMapNode>

После обновления Web.sitemapпросмотрите веб-сайт учебников в браузере. В меню слева теперь содержатся элементы для учебников по редактированию, вставке и удалению.

На карте веб-узла теперь есть записи для улучшения учебников по GridView.

Рис. 3. схема узла теперь включает в себя записи для улучшения учебников по GridView

Шаг 2. Отображение поставщиков в элементе управления GridView

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

Для начала откройте страницу RadioButtonField.aspx в папке EnhancedGridView, перетащив элемент управления GridView с панели инструментов в конструктор. Задайте для ID GridView s Suppliers и в его смарт-теге выберите Создание нового источника данных. В частности, создайте объект ObjectDataSource с именем SuppliersDataSource, который извлекает свои данные из объекта SuppliersBLL.

создать новый элемент управления ObjectDataSource с именем Супплиерсдатасаурце

Рис. 4. Создание нового элемента управления ObjectDataSource с именем SuppliersDataSource (щелкните, чтобы просмотреть изображение с полным размером)

настроить ObjectDataSource для использования класса Супплиерсблл

Рис. 5. Настройка ObjectDataSource для использования класса SuppliersBLL (щелкните, чтобы просмотреть изображение с полным размером)

Так как мы хотим вывести только поставщиков из США, выберите метод GetSuppliersByCountry(country) из раскрывающегося списка на вкладке Выбор.

настроить ObjectDataSource для использования класса Супплиерсблл

Рис. 6. Настройка ObjectDataSource для использования класса SuppliersBLL (щелкните, чтобы просмотреть изображение с полным размером)

На вкладке обновление выберите параметр (нет) и нажмите кнопку Далее.

настроить ObjectDataSource для использования класса Супплиерсблл

Рис. 7. Настройка ObjectDataSource для использования класса SuppliersBLL (щелкните, чтобы просмотреть изображение с полным размером)

Так как метод GetSuppliersByCountry(country) принимает параметр, мастер настройки источника данных запрашивает у нас источник этого параметра. Чтобы указать жестко закодированное значение (в данном примере это USA), оставьте в раскрывающемся списке Источник параметра значение нет и введите значение по умолчанию в текстовое поле. Нажмите кнопку Готово, чтобы завершить работу с мастером.

использовать USA в качестве значения по умолчанию для параметра Country

Рис. 8. Использование USA в качестве значения по умолчанию для параметра country (щелкните, чтобы просмотреть изображение с полным размером)

После завершения работы мастера GridView будет включать BoundField для каждого поля данных поставщика. Удалите все, кроме CompanyName, Cityи Country BoundFields, и переименуйте свойство CompanyName BoundFields HeaderText на поставщик. После этого декларативный синтаксис GridView и ObjectDataSource должен выглядеть следующим образом.

<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
    DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource" 
    EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="CompanyName" HeaderText="Supplier" 
            SortExpression="CompanyName" />
        <asp:BoundField DataField="City" HeaderText="City" 
            SortExpression="City" />
        <asp:BoundField DataField="Country" HeaderText="Country" 
            SortExpression="Country" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetSuppliersByCountry" TypeName="SuppliersBLL">
    <SelectParameters>
        <asp:Parameter DefaultValue="USA" Name="country" Type="String" />
    </SelectParameters>
</asp:ObjectDataSource>

В рамках этого руководства разрешить пользователю просматривать выбранные продукты поставщика на той же странице, что и список поставщиков, или на другой странице. Для этого добавьте на страницу два веб-элемента управления "Кнопка". Я настроил ID s этих двух кнопок для ListProducts и SendToProducts, предложим, что при нажатии ListProducts произойдет обратная передача, и выбранные продукты поставщика будут перечислены на той же странице, но при нажатии SendToProducts пользователь будет перейти на другую страницу со списком продуктов.

На рис. 9 показаны Suppliers GridView и два веб-элемента управления "Кнопка" при просмотре в браузере.

для поставщиков из США у вас есть сведения об имени, городе и стране.

Рис. 9. в списке поставщиков из США указаны сведения о названии, городе и стране (щелкните, чтобы просмотреть изображение с полным размером)

Шаг 3. Добавление столбца переключателей

На этом этапе Suppliers GridView имеет три BoundFields, в которых отображается название компании, город и страна каждого поставщика в США. Однако в нем по-прежнему отсутствует столбец переключателей. К сожалению, GridView не включает встроенный Радиобуттонфиелд, в противном случае мы можем просто добавить его в сетку и выполнить. Вместо этого можно добавить TemplateField и настроить его ItemTemplate для отрисовки переключателя, в результате чего будет переключатель для каждой строки GridView.

Изначально мы можем предположить, что нужный пользовательский интерфейс можно реализовать, добавив веб-элемент управления RadioButton в ItemTemplate TemplateField. Хотя это действительно добавляет один переключатель к каждой строке GridView, переключатели не могут быть сгруппированы и поэтому не являются взаимоисключающими. Это значит, что конечный пользователь может одновременно выбрать несколько переключателей из GridView.

Несмотря на то, что использование TemplateField веб-элементов управления RadioButton не предоставляет требуемых функций, давайте разберем этот подход, так как стоит изучить, почему результирующие переключатели не сгруппированы. Начните с добавления TemplateField к GridView поставщиков, сделав его крайним левым полем. Затем из смарт-тега GridView s щелкните ссылку Edit Templates (изменить шаблоны) и перетащите веб-элемент управления RadioButton из панели элементов в ItemTemplate TemplateField s (см. рис. 10). Задайте для свойства RadioButton ID значение RowSelector, а для свойства GroupName значение SuppliersGroup.

Добавление веб-элемента управления RadioButton в ItemTemplate

Рис. 10. Добавление веб-элемента управления RadioButton в ItemTemplate (щелкните, чтобы просмотреть изображение с полным размером)

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

<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
    DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource" 
    EnableViewState="False">
    <Columns>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:RadioButton ID="RowSelector" runat="server" 
                    GroupName="SuppliersGroup" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="CompanyName" HeaderText="Supplier" 
            SortExpression="CompanyName" />
        <asp:BoundField DataField="City" HeaderText="City" 
            SortExpression="City" />
        <asp:BoundField DataField="Country" HeaderText="Country" 
            SortExpression="Country" />
    </Columns>
</asp:GridView>

Свойство RadioButtonGroupName используется для группирования ряда переключателей. Все элементы управления RadioButton с одинаковым значением GroupName считаются сгруппированными. только один переключатель может быть выбран из группы за раз. Свойство GroupName задает значение для отображаемого name атрибута переключателя. Браузер проверяет переключатели, name атрибуты, чтобы определить группы переключателей.

После добавления веб-элемента управления RadioButton в ItemTemplateпосетите эту страницу в браузере и щелкните переключатели в строках сетки. Обратите внимание, что переключатели не сгруппированы, что позволяет выбрать все строки, как показано на рис. 11.

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

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

Причина, по которой переключатели не группируются, заключается в том, что их отображаемые name атрибуты различаются, несмотря на то же значение свойства GroupName. Чтобы увидеть эти различия, выполните представление/источник в браузере и изучите разметку переключателя:

<input id="ctl00_MainContent_Suppliers_ctl02_RowSelector" 
    name="ctl00$MainContent$Suppliers$ctl02$SuppliersGroup" 
    type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl03_RowSelector" 
    name="ctl00$MainContent$Suppliers$ctl03$SuppliersGroup" 
    type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl04_RowSelector" 
    name="ctl00$MainContent$Suppliers$ctl04$SuppliersGroup" 
    type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl05_RowSelector" 
    name="ctl00$MainContent$Suppliers$ctl05$SuppliersGroup" 
    type="radio" value="RowSelector" />

Обратите внимание, что атрибуты name и id не являются точными значениями, указанными в окно свойств, но добавляются в начало с числом других ID значений. Дополнительные значения ID, добавляемые в начало отображаемых id и name атрибутов, — это ID s из переключателей родительские элементы управления GridViewRow s ID s, GridView s ID, IDэлемента управления содержимым и веб-форм ID. Эти ID s добавляются таким образом, чтобы каждый отображаемый веб-элемент управления в GridView получил уникальные значения id и name.

Каждому визуализированному элементу управления требуются разные name и id, так как в этом случае браузер уникально идентифицирует каждый элемент управления на стороне клиента и как он идентифицирует веб-серверу, какое действие или изменение произошло при обратной передаче. Например, представьте, что нам нужно выполнить некоторый серверный код при изменении состояния RadioButton s. Это можно сделать, задав для свойства RadioButton AutoPostBack значение true и создав обработчик событий для события CheckChanged. Однако если отображаемые значения name и id для всех переключателей одинаковы, при обратной передаче не удалось определить, какой именно переключатель был нажат.

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

Note

Как и в случае с веб-элементом управления RadioButton, элемент управления HTML переключателя, добавляемый к шаблону, будет включать уникальный атрибут name, делая переключатели в сетке разгруппированными. Если вы не знакомы с HTML-элементами управления, вы можете проигнорировать это Примечание, так как элементы управления HTML редко используются, особенно в ASP.NET 2,0. Но если вы заинтересованы в дополнительном изучении, см. статью о веб-элементах управления иэлементах управления HTML в записи блога K. Скотт Аллен s.

Использование элемента управления Literal для внедрения разметки переключателей

Чтобы правильно сгруппировать все переключатели в GridView, необходимо вручную вставить разметку переключателей в ItemTemplate. Каждый переключатель должен иметь один и тот же атрибут name, но должен иметь уникальный атрибут id (если мы хотим получить доступ к переключателю через клиентский сценарий). После того как пользователь выберет переключатель и отправляет обратно страницу, браузер отправит значение выбранного переключателя value атрибут. Таким образом, каждому переключателю потребуется уникальный атрибут value. Наконец, при обратной передаче необходимо добавить атрибут checked к выбранному переключателю. в противном случае после того, как пользователь сделает выбор и отправит ответ, переключатели будут возвращаться к состоянию по умолчанию (все невыбранные).

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

<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>' 
    name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />

Здесь GetUniqueRadioButton и GetRadioButtonValue будут методами, определенными в классе кода программной части, который возвращал соответствующие значения атрибутов id и value для каждого переключателя. Этот подход хорошо работает при назначении атрибутов id и value, но оказывается коротким, когда требуется указать значение атрибута checked, поскольку синтаксис DataBinding выполняется только при первой привязке данных к GridView. Таким образом, если для GridView включено состояние представления, то методы форматирования будут срабатывать только при первой загрузке страницы (или при явной повторной привязке GridView к источнику данных), поэтому функция, устанавливающая checked атрибут, не будет вызываться при обратной передаче. Это довольно несложная проблема и немного выходит за рамки этой статьи, поэтому я оставлю это. Однако я рекомендую использовать описанный выше подход и работать с ним до того момента, когда вы забудете. Хотя такое упражнение не будет более близко к рабочей версии, оно поможет улучшить понимание элемента GridView и жизненного цикла привязки данных.

Другой подход к внедрению настраиваемой разметки нижнего уровня в шаблон и подход, который мы будем использовать для работы с этим руководством, — добавить к шаблону элемент управления Literal . Затем в RowCreated обработчике событий GridView s или RowDataBound к элементу управления Literal можно обращаться программно, а свойству Text — разметке для выдачи.

Начните с удаления RadioButton из TemplateField ItemTemplates, заменив его на элемент управления Literal. Задайте для свойства ID литерала значение RadioButtonMarkup.

добавить элемент управления Literal в ItemTemplate

Рис. 12. Добавление элемента управления Literal в ItemTemplate (щелкните, чтобы просмотреть изображение с полным размером)

Затем создайте обработчик событий для события RowCreated GridView s. Событие RowCreated срабатывает один раз для каждой добавляемой строки, независимо от того, выполняется ли повторное связывание данных с GridView. Это означает, что даже при обратной передаче данных из состояния представления, событие RowCreated по-прежнему срабатывает, и именно поэтому мы используем его вместо RowDataBound (который срабатывает только в том случае, если данные явно привязаны к веб-элементу управления данными).

В этом обработчике событий мы хотим продолжить, только если мы переработаем со строкой данных. Для каждой строки данных необходимо программно ссылаться на RadioButtonMarkup литеральный элемент управления и устанавливать его свойство Text в разметку для выдачи. Как показано в следующем коде, созданная разметка создает переключатель, атрибут name которого имеет значение SuppliersGroup, чей атрибут id имеет значение RowSelectorX, где X — индекс строки GridView, а атрибут value — индекс строки GridView.

protected void Suppliers_RowCreated(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // Grab a reference to the Literal control
        Literal output = (Literal)e.Row.FindControl("RadioButtonMarkup");
        // Output the markup except for the "checked" attribute
        output.Text = string.Format(
            @"<input type="radio" name="SuppliersGroup" " +
            @"id="RowSelector{0}" value="{0}" />", e.Row.RowIndex);
    }
}

Если строка GridView выбрана и выполняется обратная передача, мы заинтересованы в SupplierID выбранного поставщика. Таким образом, можно предположить, что значение каждого переключателя должно быть фактическим SupplierID (а не индексом строки GridView). Хотя это может работать в определенных обстоятельствах, угроза безопасности не принимает и не обрабатывает SupplierID. Например, наш GridView перечисляет только поставщиков в США. Однако, если SupplierID передается непосредственно из переключателя, что нужно сделать, чтобы запретить пользователю хитрый манипулировать значением SupplierID, передаваемым при обратной передаче? Используя индекс строки в качестве valueи получив SupplierID при обратной передаче из коллекции DataKeys, можно гарантировать, что пользователь использует только одно из значений SupplierID, связанных с одной из строк GridView.

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

Когда происходит обратная передача, браузер отправляет обратно name и value выбранного переключателя. Значение может быть получено программным способом с помощью Request.Form["name"]. СвойствоRequest.Form предоставляет NameValueCollection , представляющий переменные формы. Переменные формы представляют собой имена и значения полей формы на веб-странице и отправляются обратно веб-браузером каждый раз, когда происходит обратная передача. Поскольку отображаемый атрибут name переключателей в GridView имеет SuppliersGroup, при обратной передаче веб-страницы браузер отправляет SuppliersGroup=valueOfSelectedRadioButton обратно на веб-сервер (вместе с другими полями формы). Затем эти сведения можно получить из свойства Request.Form с помощью: Request.Form["SuppliersGroup"].

Так как нам нужно определить индекс выбранного переключателя не только в обработчике RowCreated событий, но и в обработчиках событий Click для веб-элементов управления "Кнопка", добавим свойство SuppliersSelectedIndex в класс кода программной части, который возвращает значение -1, если переключатель не выбран, и выбранный индекс, если выбран один из переключателей.

private int SuppliersSelectedIndex
{
    get
    {
        if (string.IsNullOrEmpty(Request.Form["SuppliersGroup"]))
            return -1;
        else
            return Convert.ToInt32(Request.Form["SuppliersGroup"]);
    }
}

После добавления этого свойства мы будем добавлять разметку checked="checked" в обработчик событий RowCreated, когда SuppliersSelectedIndex равно e.Row.RowIndex. Обновите обработчик событий, чтобы включить эту логику:

protected void Suppliers_RowCreated(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // Grab a reference to the Literal control
        Literal output = (Literal)e.Row.FindControl("RadioButtonMarkup");
        // Output the markup except for the "checked" attribute
        output.Text = string.Format(
            @"<input type="radio" name="SuppliersGroup" " +
            @"id="RowSelector{0}" value="{0}"", e.Row.RowIndex);
        // See if we need to add the "checked" attribute
        if (SuppliersSelectedIndex == e.Row.RowIndex)
            output.Text += @" checked="checked"";
        // Add the closing tag
        output.Text += " />";
    }
}

После этого изменения выбранный переключатель остается выбранным после обратной передачи. Теперь, когда у нас есть возможность указать, какой переключатель выбран, можно изменить поведение таким образом, чтобы при первом посещении страницы был выбран переключатель первого элемента GridView Row s (вместо того, чтобы ни один переключатель не был выбран по умолчанию, а это текущий поведение). Чтобы первый переключатель был выбран по умолчанию, просто измените инструкцию if (SuppliersSelectedIndex == e.Row.RowIndex) следующим образом: if (SuppliersSelectedIndex == e.Row.RowIndex || (!Page.IsPostBack && e.Row.RowIndex == 0)).

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

Note

Вместо использования TemplateField (на этом шаге 3) можно создать пользовательский класс DataControlField, который отображает соответствующий пользовательский интерфейс и функциональные возможности. КлассDataControlField является базовым классом, из которого наследуются BoundField, CheckBoxField, TemplateField и другие встроенные поля GridView и DetailsView. Создание пользовательского DataControlField класса означает, что столбец переключателей можно было бы добавить только с помощью декларативного синтаксиса, а также значительно упростить репликацию функций на других веб-страницах и других веб-приложениях.

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

Шаг 4. Отображение выбранных продуктов поставщика на отдельной странице

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

В настоящее время на странице есть два веб-элемента управления "Кнопка" ListProducts и SendToProducts. При нажатии кнопки SendToProducts необходимо отправить пользователю ~/Filtering/ProductsForSupplierDetails.aspx. Эта страница была создана в учебнике " основной/подробности" в двух страницах и отображает продукты для поставщика, SupplierID передается через поле QueryString с именем SupplierID.

Чтобы предоставить эти функциональные возможности, создайте обработчик событий для Click события кнопки SendToProducts. На шаге 3 мы добавили свойство SuppliersSelectedIndex, которое возвращает индекс строки, переключатель которой выбран. Соответствующий SupplierID можно получить из коллекции GridView s DataKeys и пользователь может отправить ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID с помощью Response.Redirect("url").

protected void SendToProducts_Click(object sender, EventArgs e)
{
    // Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
    int supplierID = 
        Convert.ToInt32(Suppliers.DataKeys[SuppliersSelectedIndex].Value);
    Response.Redirect(
        "~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" 
        + supplierID);
    }
}

Этот код работает замечательно, пока один из переключателей выбран из GridView. Если изначально элемент управления GridView не имеет выбранных переключателей и пользователь нажимает кнопку SendToProducts, SuppliersSelectedIndex будет -1, что приведет к возникновению исключения, так как -1 находится вне диапазона индекса DataKeys коллекции. Однако это не является проблемой, но если вы решили обновить обработчик событий RowCreated, как описано в шаге 3, чтобы сначала был выбран первый переключатель в GridView.

Чтобы разместить SuppliersSelectedIndex значение -1, добавьте веб-элемент управления Label на страницу над GridView. Задайте для свойства ID значение ChooseSupplierMsg, его свойство CssClass для Warning, свойства EnableViewState и Visible в false, а также свойство Text, чтобы выбрать поставщика из сетки. Класс CSS Warning отображает текст красным, курсивным шрифтом, большим шрифтом и определяется в Styles.css. Установив для свойств EnableViewState и Visible значение false, метка не подготавливается к просмотру, кроме тех случаев, когда свойству Visible элемента управления программным образом присваивается значение true.

добавить веб-элемент управления Label над GridView

Рис. 13. Добавление веб-элемента управления Label над элементом GridView (щелкните, чтобы просмотреть изображение с полным размером)

Затем дополните обработчик событий Click, чтобы отобразить ChooseSupplierMsg метку, если SuppliersSelectedIndex меньше нуля, и перенаправить пользователя на ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID в противном случае.

protected void SendToProducts_Click(object sender, EventArgs e)
{
    // make sure one of the radio buttons has been selected
    if (SuppliersSelectedIndex < 0)
        ChooseSupplierMsg.Visible = true;
    else
    {
        // Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
        int supplierID = 
            Convert.ToInt32(Suppliers.DataKeys[SuppliersSelectedIndex].Value);
        Response.Redirect(
            "~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" 
            + supplierID);
    }
}

Перейдите на страницу в браузере и нажмите кнопку SendToProducts перед выбором поставщика из GridView. Как показано на рис. 14, отображается метка ChooseSupplierMsg. Затем выберите поставщика и нажмите кнопку SendToProducts. Это позволит вам перенесет на страницу со списком продуктов, предоставленных выбранным поставщиком. На рис. 15 показана страница ProductsForSupplierDetails.aspx при выборе поставщика Бигфут Бревериес.

отображается метка Чусесупплиермсг, если не выбран поставщик

Рис. 14. метка ChooseSupplierMsg отображается, если не выбран поставщик (щелкните, чтобы просмотреть изображение с полным размером)

выбранные продукты поставщика отображаются в Продуктсфорсупплиердетаилс. aspx.

Рис. 15. выбранные продукты поставщика отображаются в ProductsForSupplierDetails.aspx (щелкните, чтобы просмотреть изображение с полным размером)

Шаг 5. Отображение выбранных продуктов поставщика на той же странице

На шаге 4 мы видели, как отправить пользователя на другую веб-страницу для отображения выбранных продуктов поставщика. Кроме того, выбранные продукты поставщика могут отображаться на одной и той же странице. Чтобы проиллюстрировать это, мы добавим еще один элемент управления GridView для RadioButtonField.aspx для просмотра выбранных продуктов поставщика.

Так как мы хотим, чтобы этот элемент GridView продуктов отображался только после выбора поставщика, добавьте веб-элементы управления Panel под Suppliers GridView, задав для его ID значение ProductsBySupplierPanel, а для свойства Visible — значение false. На панели добавьте текстовые продукты для выбранного поставщика, а затем элемент управления GridView с именем ProductsBySupplier. В смарт-теге GridView s выберите привязку к новому ObjectDataSource с именем ProductsBySupplierDataSource.

привязки элемента управления GridView Продуктсбисупплиер к новому элементу управления ObjectDataSource

Рис. 16. Привязка ProductsBySupplier GridView к новому элементу управления ObjectDataSource (щелкните, чтобы просмотреть изображение с полным размером)

Затем настройте ObjectDataSource для использования класса ProductsBLL. Так как мы хотим получить только те продукты, которые предоставлены выбранным поставщиком, необходимо указать, что ObjectDataSource должен вызвать метод GetProductsBySupplierID(supplierID) для получения своих данных. Выберите (нет) в раскрывающихся списках на вкладках обновление, вставка и удаление.

настроить ObjectDataSource для использования метода Жетпродуктсбисупплиерид (КодПоставщика)

Рис. 17. Настройка ObjectDataSource для использования метода GetProductsBySupplierID(supplierID) (щелкните, чтобы просмотреть изображение с полным размером)

установка в раскрывающихся списках (нет) на вкладках «обновить», «вставить» и «удалить»

Рис. 18. Установка в раскрывающихся списках (нет) на вкладках "Обновить", "вставить" и "Удалить" (щелкните, чтобы просмотреть изображение с полным размером)

После настройки вкладок выбор, обновление, вставка и удаление нажмите кнопку Далее. Так как метод GetProductsBySupplierID(supplierID) ожидает входный параметр, мастер создания источника данных предлагает указать источник для значения параметра s.

Здесь есть несколько вариантов указания источника значения параметра s. Мы могли бы использовать объект параметра по умолчанию и программно назначить значение свойства SuppliersSelectedIndex свойству DefaultValue параметра в обработчике событий ObjectDataSource Selecting. Вернитесь к руководству по программному заданию значений параметров ObjectDataSource в руководстве по программному назначению значений параметрам ObjectDataSource s.

Кроме того, можно использовать ControlParameter и обратиться к свойству Suppliers GridView sSelectedValue (см. рис. 19). Свойство SelectedValue GridView s возвращает значение DataKey, соответствующее свойствуSelectedIndex. Чтобы этот параметр работал, необходимо программно задать свойство SelectedIndex GridView s для выбранной строки при нажатии кнопки ListProducts. В качестве дополнительного преимущества, установив SelectedIndex, выбранная запись будет принимать SelectedRowStyle, определенные в DataWebControlsой теме (желтый фон).

использовать ControlParameter, чтобы указать GridView s SelectedValue в качестве источника параметра.

Рис. 19. Использование ControlParameter для указания GridView s SelectedValue в качестве источника параметра (щелкните, чтобы просмотреть изображение с полным размером)

После завершения работы мастера Visual Studio автоматически добавит поля для полей данных Product. Удалите все, кроме ProductName, CategoryNameи UnitPrice BoundFields, а также измените свойства HeaderText на "продукт", "Категория" и "цена". Настройте UnitPrice BoundField, чтобы его значение было отформатировано как денежная единица. После внесения этих изменений декларативная разметка Panel, GridView и ObjectDataSource должна выглядеть следующим образом:

<asp:Panel runat="server" ID="ProductsBySupplierPanel" Visible="False">
    <h3>
        Products for the Selected Supplier</h3>
    <p>
        <asp:GridView ID="ProductsBySupplier" runat="server" 
            AutoGenerateColumns="False" DataKeyNames="ProductID"
            DataSourceID="ProductsBySupplierDataSource" EnableViewState="False">
            <Columns>
                <asp:BoundField DataField="ProductName" HeaderText="Product" 
                    SortExpression="ProductName" />
                <asp:BoundField DataField="CategoryName" HeaderText="Category" 
                    ReadOnly="True" SortExpression="CategoryName" />
                <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" 
                    HeaderText="Price" HtmlEncode="False" 
                    SortExpression="UnitPrice" />
            </Columns>
        </asp:GridView>
        <asp:ObjectDataSource ID="ProductsBySupplierDataSource" runat="server" 
            OldValuesParameterFormatString="original_{0}"
            SelectMethod="GetProductsBySupplierID" TypeName="ProductsBLL">
            <SelectParameters>
                <asp:ControlParameter ControlID="Suppliers" Name="supplierID" 
                    PropertyName="SelectedValue" Type="Int32" />
            </SelectParameters>
        </asp:ObjectDataSource>
    </p>
</asp:Panel>

Для выполнения этого упражнения необходимо задать для свойства SelectedIndex GridView s значение SelectedSuppliersIndex а для свойства Visible панели ProductsBySupplierPanel — значение true при нажатии кнопки ListProducts. Для этого создайте обработчик событий для Click события ListProducts Web Control Button и добавьте следующий код:

protected void ListProducts_Click(object sender, EventArgs e)
{
    // make sure one of the radio buttons has been selected
    if (SuppliersSelectedIndex < 0)
    {
        ChooseSupplierMsg.Visible = true;
        ProductsBySupplierPanel.Visible = false;
    }
    else
    {
        // Set the GridView's SelectedIndex
        Suppliers.SelectedIndex = SuppliersSelectedIndex;
        // Show the ProductsBySupplierPanel panel
        ProductsBySupplierPanel.Visible = true;
    }
}

Если поставщик не был выбран из GridView, отображается ChooseSupplierMsg метка, а панель ProductsBySupplierPanel скрыта. В противном случае, если выбран поставщик, ProductsBySupplierPanel отображается и свойство GridView s SelectedIndex обновляется.

На рис. 20 показаны результаты после выбора поставщика Бигфут Бревериес и нажатия кнопки Показать продукты на странице.

продукты, предоставляемые Бигфут Бревериес, перечислены на одной странице.

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

Сводка

Как обсуждалось в разделе " Основные/подробности" с помощью DetailView главного GridView с учебником "подробности", записи можно выбрать из GridView с помощью CommandField, свойство ShowSelectButton которого имеет значение true. Но CommandField отображает свои кнопки как обычные кнопки, ссылки или изображения. Альтернативным пользовательским интерфейсом выбора строк является предоставление переключателя или флажка в каждой строке GridView. В этом учебнике мы рассмотрели, как добавить столбец переключателей.

К сожалению, Добавление столбца переключателей t не так просто, как можно ожидать. Нет встроенных Радиобуттонфиелд, которые можно добавить при нажатии кнопки, а использование веб-элемента управления RadioButton в TemplateField вводит собственный набор проблем. В итоге, чтобы предоставить такой интерфейс, необходимо создать пользовательский класс DataControlField или попытаться внедрить соответствующий HTML-код в TemplateField во время события RowCreated.

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

Поздравляем с программированием!

Об авторе

Скотт Митчелл, автор семи книг по ASP/ASP. NET и основатель 4GuysFromRolla.com, работал с веб-технологиями Майкрософт с 1998. Скотт работает как независимый консультант, преподаватель и модуль записи. Его последняя книга — Sams обучать себя ASP.NET 2,0 за 24 часа. Он доступен по адресу mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.

Специальная благодарность

Эта серия руководств была рассмотрена многими полезными рецензентами. Специалистом по интересу для работы с этим руководством был Дэвид суру. Хотите ознакомиться с моими будущими статьями MSDN? Если это так, расположите строку в mitchell@4GuysFromRolla.com.