Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом учебнике рассматривается, как добавить столбец переключателей в элемент управления GridView, чтобы предоставить пользователю более интуитивно понятный способ выбора одной строки GridView.
Введение
Элемент управления GridView предлагает множество встроенных функций. Он включает в себя ряд различных полей для отображения текста, изображений, гиперссылок и кнопок. Он поддерживает шаблоны для дальнейшей кастомизации. С помощью нескольких щелчков мыши можно создать GridView, где каждую строку можно выбрать с помощью кнопки, или включить возможность редактирования или удаления. Несмотря на обилие предоставляемых функций, часто возникают ситуации, в которых необходимо добавить дополнительные, неподдерживаемые функции. В этом и следующих двух уроках мы рассмотрим, как расширить функциональность GridView, включив в нее дополнительные функции.
Этот и следующий уроки посвящены улучшению процесса выбора строк. Как было рассмотрено в разделе Основной/Подробный учет с использованием выбираемого основного GridView с Details DetailView, мы можем добавить CommandField в GridView, который включает кнопку Select. При нажатии на него происходит обратная передача, и свойство GridView SelectedIndex
обновляется до индекса строки, в которой была нажата кнопка Выбрать. В учебном пособии по Master/Detail Using a Selectable Master GridView with a Details DetailView мы рассмотрели, как использовать эту функцию для отображения деталей для выбранной строки GridView.
Хотя кнопка «Выбрать» работает во многих ситуациях, она может работать не так хорошо для других. Вместо использования кнопки для выбора обычно используются два других элемента пользовательского интерфейса: переключатель и флажок. Мы можем дополнить GridView так, чтобы вместо кнопки Select каждая строка содержала переключатель или флажок. В сценариях, в которых пользователь может выбрать только одну из записей GridView, переключатель может быть предпочтительнее, чем кнопка Выбрать. В ситуациях, когда пользователь потенциально может выбрать несколько записей, например в веб-приложении электронной почты, где пользователь может захотеть выбрать несколько сообщений для удаления, флажок предлагает функцию, недоступную в пользовательском интерфейсе кнопки «Выбрать» или переключателя.
В этом руководстве показано, как добавить столбец переключателей в GridView. В следующем уроке мы исследуем использование флажков.
Шаг 1: Создание улучшения веб-страниц GridView
Прежде чем мы начнем улучшать GridView, добавляя в него столбец переключателей, давайте сначала уделим немного времени созданию ASP.NET страниц в нашем проекте веб-сайта, которые нам понадобятся для этого урока и следующих двух. Сначала добавьте новую папку с именем EnhancedGridView
. Затем добавьте в нее следующие ASP.NET страницы, чтобы связать каждую страницу с главной страницей Site.master
:
Default.aspx
RadioButtonField.aspx
CheckBoxField.aspx
InsertThroughFooter.aspx
Рис. 1. Добавление страниц ASP.NET для учебников SqlDataSource-Related
Как и в других папках, Default.aspx
в папке EnhancedGridView
перечислены учебные материалы в соответствующем разделе. Помните, что элемент SectionLevelTutorialListing.ascx
управления пользователем предоставляет эту функцию. Поэтому добавьте этот элемент управления Default.aspx
пользователем, перетащив его из Обозреватель решений в представление конструктора страницы.
Рис. 2. Добавьте элемент управления пользователя SectionLevelTutorialListing.ascx
в Default.aspx
(щелкните, чтобы просмотреть изображение в полном размере)
Наконец, добавьте эти четыре страницы в качестве записей в Web.sitemap
файл. В частности, добавьте следующую разметку после элемента управления <siteMapNode>
Using the 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
найдите минутку и посмотрите сайт с учебными материалами через браузер. Меню слева теперь содержит элементы для редактирования, вставки и удаления учебников.
Рисунок 3: Карта сайта теперь включает записи для уроков по улучшению GridView
Шаг 2: Отображение поставщиков в GridView
Для этого урока давайте создадим GridView, в котором будут перечислены поставщики из США, причем каждая строка GridView будет иметь переключатель. После выбора поставщика с помощью радиокнопки пользователь может просмотреть продукцию поставщика, нажав кнопку. Хотя эта задача может показаться тривиальной, есть ряд тонкостей, которые делают ее особенно сложной. Прежде чем мы углубимся в эти тонкости, давайте сначала получим GridView со списком поставщиков.
Начните с RadioButtonField.aspx
открытия страницы в папке, EnhancedGridView
перетащив GridView с панели элементов в конструктор. Установите для параметра GridView s ID
значение и Suppliers
с помощью смарт-тега выберите создание нового источника данных. В частности, создайте ObjectDataSource с именем SuppliersDataSource
, который извлекает данные из SuppliersBLL
объекта.
Рисунок 4: Создание нового ObjectDataSource с именем SuppliersDataSource
(Нажмите, чтобы просмотреть полноразмерное изображение)
Рис. 5. Настройка ObjectDataSource для использования SuppliersBLL
класса (щелкните, чтобы просмотреть изображение полного размера)
Поскольку мы хотим перечислить только тех поставщиков в США, выберите GetSuppliersByCountry(country)
метод из выпадающего списка на вкладке ВЫБРАТЬ.
Рис. 6. Настройка ObjectDataSource для использования SuppliersBLL
класса (щелкните, чтобы просмотреть изображение полного размера)
На вкладке «ОБНОВИТЬ» выберите параметр (Нет) и нажмите «Далее».
Рисунок 7: Настройка ObjectDataSource для использования SuppliersBLL
класса (Нажмите, чтобы просмотреть полноразмерное изображение)
GetSuppliersByCountry(country)
Поскольку метод принимает параметр, мастер настройки источника данных запрашивает у нас источник этого параметра. Чтобы указать жестко заданное значение (в данном примере США), оставьте в раскрывающемся списке Источник параметра значение Нет и введите значение по умолчанию в текстовое поле. Нажмите кнопку "Готово", чтобы завершить работу мастера.
Рисунок 8: Используйте США в качестве значения по умолчанию для параметра country
(Нажмите, чтобы просмотреть полноразмерное изображение)
После завершения работы мастера GridView будет включать BoundField для каждого из полей данных поставщика. Удалите все, кроме , CompanyName
, City
и Country
BoundFields, и переименуйте свойство CompanyName
BoundFields HeaderText
в Supplier. После этого декларативный синтаксис 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>
В этом уроке давайте позволим пользователю просматривать продукты выбранного поставщика на той же странице, что и список поставщиков, или на другой странице. Чтобы приспособиться к этому, добавьте на страницу два элемента управления Button Web. Я установил ID
s этих двух кнопок в положение ListProducts
и SendToProducts
, с идеей, что при ListProducts
нажатии произойдет постбек, и продукты выбранного поставщика будут перечислены на той же странице, но при SendToProducts
нажатии пользователь будет перенаправлен на другую страницу, на которой перечислены продукты.
На рисунке Suppliers
9 показаны элементы управления GridView и два элемента управления Button Web при просмотре через браузер.
Рисунок 9: У поставщиков из США указана информация о их имени, городе и стране (Нажмите, чтобы просмотреть изображение в полном размере)
Шаг 3: Добавление колонки радиокнопок
На этом этапе Suppliers
GridView имеет три поля BoundField, отображающие название компании, город и страну каждого поставщика в США. Тем не менее, ему все еще не хватает колонки радиокнопок. К сожалению, GridView не включает в себя встроенное поле RadioButtonField, иначе мы могли бы просто добавить его в сетку и готово. Вместо этого мы можем добавить TemplateField и настроить его ItemTemplate
для рендеринга переключателя, что приведет к созданию переключателя для каждой строки GridView.
Первоначально можно предположить, что желаемый пользовательский интерфейс может быть реализован путем добавления веб-элемента управления RadioButton в ItemTemplate
поле TemplateField. Хотя это действительно добавит по одному переключателю в каждую строку GridView, переключатели не могут быть сгруппированы и поэтому не являются взаимоисключающими. Это означает, что конечный пользователь может выбрать несколько переключателей одновременно в GridView.
Несмотря на то, что использование TemplateField веб-элементов управления RadioButton не обеспечивает необходимой нам функциональности, давайте реализуем этот подход, поскольку стоит проверить, почему результирующие переключатели не сгруппированы. Начните с добавления TemplateField в Suppliers GridView, сделав его крайним левым полем. Затем в смарт-теге GridView щелкните ссылку Edit Templates и перетащите веб-элемент управления RadioButton с панели инструментов в TemplateField s ItemTemplate
(см. рис. 10). Установите для свойства RadioButton s ID
значение и RowSelector
для GroupName
свойства .SuppliersGroup
Рисунок 10: Добавление веб-элемента управления RadioButton к (ItemTemplate
Нажмите, чтобы просмотреть полноразмерное изображение)
После внесения этих дополнений через дизайнер разметка вашего GridView должна выглядеть примерно так:
<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>
Свойство RadioButton — GroupName
это то, что используется для группировки ряда переключателей. Все элементы управления RadioButton с одинаковым GroupName
значением считаются сгруппированными; в каждый момент времени из группы можно выбрать только одну радиокнопку. Свойство GroupName
указывает значение атрибута отображаемого радиокнопки s name
. Браузер проверяет атрибуты радиокнопок name
для определения группировок радиокнопок.
С добавлением веб-элемента управления RadioButton в , ItemTemplate
перейдите на эту страницу через браузер и нажмите на переключатели в строках сетки. Обратите внимание, что переключатели не сгруппированы, что позволяет выбрать все строки, как показано на рисунке 11.
Рисунок 11: Переключатели GridView не сгруппированы (Нажмите, чтобы просмотреть полноразмерное изображение)
Причина, по которой переключатели не сгруппированы, заключается в том, что их отображаемые name
атрибуты различаются, несмотря на одинаковые GroupName
настройки свойств. Чтобы увидеть эти различия, выполните View/Source из браузера и изучите разметку переключателей:
<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
and id
не являются точными значениями, указанными в окне Properties, но предваряются рядом других ID
значений. Дополнительными значениями, ID
добавленными в переднюю часть отображаемого id
и name
атрибутов, являются s родительских элементов управления ID
переключателямиGridViewRow
, s s, GridView ID
, элемента управления ID
содержимым s , и s ID
веб-формы.ID
Эти ID
элементы добавляются для того, чтобы каждый визуализированный веб-элемент управления в GridView имел уникальные id
значения and name
.
Каждый визуализированный элемент управления должен быть разным name
id
, и именно так браузер однозначно идентифицирует каждый элемент управления на стороне клиента и как он идентифицирует веб-сервер, какое действие или изменение произошло при обратной передаче. Например, представьте, что мы хотим запускать некоторый код на стороне сервера всякий раз, когда проверяемое состояние RadioButton изменяется. Мы могли бы достичь этого, установив свойство RadioButton AutoPostBack
в значение True
и создав обработчик событий для события CheckChanged
. Однако, если бы рендер name
и id
значения для всех радиокнопок были одинаковыми, на постбеке мы не могли бы определить, какая конкретно RadioButton была нажата.
Вкратце мы не можем создать колонку переключателей в GridView с помощью веб-элемента управления RadioButton. Вместо этого мы должны использовать довольно архаичные методы, чтобы гарантировать, что соответствующая разметка внедряется в каждую строку GridView.
Замечание
Как и веб-элемент управления RadioButton, элемент управления HTML переключатель при добавлении в шаблон будет включать атрибут unique name
, что делает переключатели в сетке разгруппированными. Если вы не знакомы с элементами управления HTML, не стесняйтесь игнорировать это замечание, так как элементы управления HTML используются редко, особенно в ASP.NET 2.0. Но если вы хотите узнать больше, см. запись в блоге К. Скотта Аллена«Веб-элементы управления и элементы управления HTML».
Использование литерального элемента управления для внедрения разметки переключателя
Чтобы правильно сгруппировать все переключатели в GridView, нам нужно вручную внедрить разметку переключателей в .ItemTemplate
Каждый переключатель должен иметь один и тот же name
атрибут, но должен иметь уникальный id
атрибут (на случай, если мы хотим получить доступ к радиокнопке через скрипт на стороне клиента). После того, как пользователь выберет радиокнопку и отправит сообщение на страницу, браузер отправит обратно значение атрибута выбранного радиокнопки s value
. Поэтому каждой радиокнопке потребуется уникальный value
атрибут. Наконец, на постбеке нам нужно убедиться, что добавили атрибут checked
к одному выбранному переключателю, иначе после того, как пользователь сделает выбор и отправит сообщение, радиокнопки вернутся в свое состояние по умолчанию (все невыбранные).
Существует два подхода, которые можно использовать для внедрения низкоуровневой разметки в шаблон. Один из них заключается в том, чтобы выполнить сочетание разметки и вызовов методов форматирования, определенных в классе кода программной части. Этот метод впервые был рассмотрен в руководстве по использованию TemplateFields в элементе управления GridView . В нашем случае это может выглядеть примерно так:
<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>'
name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />
Здесь и GetUniqueRadioButton
будут методы, определенные в классе кода программной части, GetRadioButtonValue
которые возвращают соответствующие id
значения атрибутов и value
для каждого переключателя. Этот подход хорошо подходит для назначения атрибутов id
and value
, но не подходит для указания значения атрибута checked
, поскольку синтаксис привязки данных выполняется только при первой привязке данных к GridView. Таким образом, если в GridView включено состояние просмотра, методы форматирования будут срабатывать только при первой загрузке страницы (или при явном привязке GridView к источнику данных), и поэтому функция, устанавливающая атрибут, checked
не будет вызываться при обратной передаче. Это довольно тонкая проблема, которая немного выходит за рамки этой статьи, поэтому я оставлю ее на этом. Тем не менее, я призываю вас попробовать использовать описанный выше подход и проработать его до тех пор, пока вы не застрянете. Хотя такое упражнение не приблизит вас к рабочей версии, оно поможет лучше понять GridView и жизненный цикл привязки данных.
Другой подход к внедрению пользовательской, низкоуровневой разметки в шаблон и подход, который мы будем использовать в этом руководстве, заключается в добавлении литерального элемента управления в шаблон. Затем, в GridView s RowCreated
или RowDataBound
обработчике событий, можно программно получить доступ к литеральному элементу управления и установить его Text
свойство в разметку для генерации.
Начните с удаления RadioButton из TemplateField s ItemTemplate
, заменив его литеральным элементом управления. Установите литеральный элемент управления s ID
в положение RadioButtonMarkup
.
Рисунок 12: Добавление литерального элемента управления к (ItemTemplate
Нажмите, чтобы просмотреть полноразмерное изображение)
Далее создайте обработчик события для события GridView RowCreated
. Событие RowCreated
запускается один раз для каждой добавленной строки, независимо от того, возвращаются ли данные в GridView. Это означает, что даже при обратной передаче, когда данные перезагружаются из состояния просмотра, событие все равно срабатывает, и именно по этой причине мы используем его вместо него RowCreated
(который срабатывает только тогда, RowDataBound
когда данные явно привязаны к веб-элементу управления данными).
В этом обработчике событий мы хотим продолжить работу только в том случае, если мы имеем дело со строкой данных. Для каждой строки данных мы хотим программно ссылаться на RadioButtonMarkup
элемент управления Literal и установить его Text
свойство в разметку, которую нужно выдать. Как показано в следующем коде, создаваемая разметка создает переключатель, для атрибута которого name
задано значение SuppliersGroup
, для id
атрибута которого задано значение RowSelectorX
, где X — индекс строки GridView, а value
для атрибута — индекс строки GridView.
Protected Sub Suppliers_RowCreated(sender As Object, e As GridViewRowEventArgs) _
Handles Suppliers.RowCreated
If e.Row.RowType = DataControlRowType.DataRow Then
' Grab a reference to the Literal control
Dim output As Literal = _
CType(e.Row.FindControl("RadioButtonMarkup"), Literal)
' 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)
End If
End Sub
Когда выбрана строка GridView и происходит обратная передача, нас интересует строка SupplierID
выбранного поставщика. Поэтому можно подумать, что значение каждой радиокнопки должно быть фактическим SupplierID
(а не индексом строки GridView). Хотя в определенных обстоятельствах это может сработать, слепое принятие и обработка домена SupplierID
. Наш GridView, например, перечисляет только тех поставщиков, которые находятся в США. Однако, если сигнал SupplierID
передается непосредственно с радиокнопки, что может помешать злоумышленнику манипулировать значением SupplierID
, отправленным обратно на postback? Используя индекс строки в качестве value
, а затем получая SupplierID
обратную передачу on из 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
обработчиках событий для элементов управления Button Web, давайте добавим свойство SuppliersSelectedIndex
в класс кода программной части, которое возвращает -1
, если переключатель не был выбран, и выбранный индекс, если выбран один из переключателей.
Private ReadOnly Property SuppliersSelectedIndex() As Integer
Get
If String.IsNullOrEmpty(Request.Form("SuppliersGroup")) Then
Return -1
Else
Return Convert.ToInt32(Request.Form("SuppliersGroup"))
End If
End Get
End Property
С добавлением этого свойства мы знаем, что нужно добавить разметку checked="checked"
в RowCreated
обработчик событий, когда SuppliersSelectedIndex
значение e.Row.RowIndex
равно . Обновите обработчик событий, включив в него следующую логику:
Protected Sub Suppliers_RowCreated(sender As Object, e As GridViewRowEventArgs) _
Handles Suppliers.RowCreated
If e.Row.RowType = DataControlRowType.DataRow Then
' Grab a reference to the Literal control
Dim output As Literal = _
CType(e.Row.FindControl("RadioButtonMarkup"), Literal)
' 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 Then
output.Text &= " checked="checked""
End If
' Add the closing tag
output.Text &= " />"
End If
End Sub
При этом выбранный переключатель остается выбранным после постбека. Теперь, когда у нас есть возможность указать, какой переключатель будет выбран, мы можем изменить поведение таким образом, чтобы при первом посещении страницы был выбран первый переключатель строки GridView (вместо того, чтобы не выбирать переключатели по умолчанию, как это происходит в настоящее время). Чтобы выбрать первый переключатель по умолчанию, просто измените If SuppliersSelectedIndex = e.Row.RowIndex Then
оператор на следующий: If SuppliersSelectedIndex = e.Row.RowIndex OrElse (Not Page.IsPostBack AndAlso e.Row.RowIndex = 0) Then
.
На данный момент мы добавили столбец сгруппированных переключателей в GridView, который позволяет выбрать одну строку GridView и запомнить ее во всех обратных передачах. Нашими следующими шагами являются показ продуктов, предоставленных выбранным поставщиком. В Шаге 4 мы рассмотрим, как перенаправить пользователя на другую страницу, отправив по нему выбранный SupplierID
файл . На шаге 5 мы увидим, как отобразить продукты выбранного поставщика в GridView на той же странице.
Замечание
Вместо использования TemplateField (о котором идет речь в этом длинном шаге 3), мы могли бы создать пользовательский DataControlField
класс, который отображает соответствующий пользовательский интерфейс и функциональность.
КлассDataControlField
является базовым классом, от которого происходят BoundField, CheckBoxField, TemplateField и другие встроенные поля GridView и DetailsView. Создание пользовательского DataControlField
класса означало бы, что колонка переключателей могла бы быть добавлена просто с помощью декларативного синтаксиса, а также значительно упростило бы репликацию функциональности на других веб-страницах и других веб-приложениях.
Однако, если вы когда-либо создавали пользовательские, скомпилированные элементы управления в ASP.NET, вы знаете, что это требует изрядной работы и сопряжено с множеством тонкостей и крайних случаев, с которыми нужно обращаться осторожно. Поэтому мы пока откажемся от реализации колонки переключателей в качестве пользовательского DataControlField
класса и остановимся на опции TemplateField. Возможно, у нас будет возможность изучить создание, использование и развертывание пользовательских DataControlField
классов в следующем руководстве!
Шаг 4: Отображение товаров выбранного поставщика на отдельной странице
После того, как пользователь выбрал строку GridView, нам нужно показать продукты выбранного поставщика. В некоторых случаях мы можем захотеть отобразить эти продукты на отдельной странице, в других случаях мы можем предпочесть сделать это на той же странице. Давайте сначала рассмотрим, как отобразить товары на отдельной странице; В Шаге 5 мы рассмотрим добавление GridView для RadioButtonField.aspx
отображения продуктов выбранного поставщика.
В настоящее время на странице ListProducts
есть два элемента управления Button Web и SendToProducts
. При нажатии на SendToProducts
кнопку мы хотим отправить пользователя в ~/Filtering/ProductsForSupplierDetails.aspx
. Эта страница была создана в учебном пособии по фильтрации основных и подробных данных на двух страницах и отображает продукты для поставщика, которые SupplierID
проходят через поле строки запроса с именем SupplierID
.
Чтобы обеспечить эту функциональность, создайте обработчик событий для SendToProducts
события Button s Click
. В Шаге 3 мы добавили SuppliersSelectedIndex
свойство, которое возвращает индекс строки, переключатель которой выбран. Соответствующий SupplierID
файл может быть извлечен из коллекции GridView, DataKeys
а затем пользователь может быть отправлен с ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
помощью Response.Redirect("url")
.
Protected Sub SendToProducts_Click(sender As Object, e As EventArgs) _
Handles SendToProducts.Click
' Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
Dim supplierID As Integer = _
Convert.ToInt32(Suppliers.DataKeys(SuppliersSelectedIndex).Value)
Response.Redirect( _
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" & _
supplierID)
End Sub
Этот код прекрасно работает, если одна из радиокнопок выбрана в GridView. Если изначально в GridView не выбраны переключатели и пользователь нажимает кнопку SendToProducts
, SuppliersSelectedIndex
то будет , -1
что приведет к возникновению исключения, так как -1
находится за пределами индексного диапазона DataKeys
коллекции. Однако это не проблема, если вы решили обновить RowCreated
обработчик событий, как описано в шаге 3, чтобы изначально выбрать первый переключатель в GridView.
Чтобы учесть SuppliersSelectedIndex
значение -1
, добавьте элемент управления Label Web на страницу над GridView. Установите его ID
свойство в значение ChooseSupplierMsg
, его CssClass
свойство в значение Warning
, его EnableViewState
и Visible
свойства в значение False
, а его Text
свойство в положение Пожалуйста, выберите поставщика из сетки. Класс Warning
CSS отображает текст красным, курсивом, полужирным, крупным шрифтом и определяется в Styles.css
. При установке EnableViewState
свойств and Visible
в значение False
, метка не визуализируется, за исключением тех постбэков, где свойство s элемента управления Visible
программно установлено в значение True
.
Рисунок 13: Добавление веб-элемента управления метками над GridView (Нажмите, чтобы просмотреть полноразмерное изображение)
Затем увеличьте Click
обработчик событий, чтобы отображать ChooseSupplierMsg
Label if SuppliersSelectedIndex
меньше нуля, и перенаправьте пользователя на ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
страницу else.
Protected Sub SendToProducts_Click(sender As Object, e As EventArgs) _
Handles SendToProducts.Click
' make sure one of the radio buttons has been selected
If SuppliersSelectedIndex < 0 Then
ChooseSupplierMsg.Visible = True
Else
' Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
Dim supplierID As Integer = _
Convert.ToInt32(Suppliers.DataKeys(SuppliersSelectedIndex).Value)
Response.Redirect( _
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" & _
supplierID)
End If
End Sub
Перейдите на страницу в браузере и нажмите кнопку SendToProducts
перед выбором поставщика из GridView. Как показано на рисунке 14, здесь отображается ChooseSupplierMsg
метка. Далее выберите поставщика и нажмите SendToProducts
кнопку. Это приведет вас на страницу, на которой перечислены продукты, поставляемые выбранным поставщиком. На рисунке 15 показана страница, ProductsForSupplierDetails.aspx
на которой был выбран поставщик Bigfoot Breweries.
Рисунок 14: Этикетка отображается, ChooseSupplierMsg
если поставщик не выбран (нажмите, чтобы просмотреть полноразмерное изображение)
Рисунок 15: Продукты выбранного поставщика отображаются в ProductsForSupplierDetails.aspx
(Нажмите, чтобы просмотреть изображение в полном размере)
Шаг 5: Отображение продуктов выбранного поставщика на одной странице
В Шаге 4 мы увидели, как отправить пользователя на другую веб-страницу для отображения товаров выбранного поставщика. Кроме того, продукты выбранного поставщика могут быть отображены на той же странице. Чтобы проиллюстрировать это, мы добавим еще один GridView для RadioButtonField.aspx
отображения продуктов выбранного поставщика.
Поскольку мы хотим, чтобы этот GridView продуктов отображался только после выбора поставщика, добавьте веб-элемент управления Panel под GridView, установив Suppliers
для него ID
значение и ProductsBySupplierPanel
его Visible
свойства в значение False
. На панели добавьте текст Products для выбранного поставщика, за которым следует GridView с именем ProductsBySupplier
. В смарт-теге GridView выберите привязку его к новому ObjectDataSource с именем ProductsBySupplierDataSource
.
Рисунок 16: Привязка ProductsBySupplier
GridView к новому ObjectDataSource (Нажмите, чтобы просмотреть полноразмерное изображение)
Затем настройте ObjectDataSource для использования ProductsBLL
класса. Поскольку мы хотим получить только те продукты, которые предоставлены выбранным поставщиком, укажите, что ObjectDataSource должен вызывать GetProductsBySupplierID(supplierID)
метод для получения своих данных. Выберите (Нет) из раскрывающихся списков на вкладках ОБНОВИТЬ, ВСТАВИТЬ и УДАЛИТЬ.
Рисунок 17: Настройка ObjectDataSource для использования GetProductsBySupplierID(supplierID)
метода (Нажмите, чтобы просмотреть полноразмерное изображение)
Рисунок 18: Установите Drop-Down Lists в положение (None) на вкладках UPDATE, INSERT и DELETE (Нажмите, чтобы просмотреть полноразмерное изображение)
После настройки вкладок SELECT, UPDATE, INSERT и DELETE нажмите кнопку Next.
GetProductsBySupplierID(supplierID)
Поскольку метод ожидает входной параметр, мастер создания источника данных предлагает нам указать источник для значения параметра s.
Здесь у нас есть несколько вариантов указания источника значения параметра s. Мы могли бы использовать объект Parameter по умолчанию и программно присвоить значение SuppliersSelectedIndex
свойства свойству Parameter s DefaultValue
в обработчике событий ObjectDataSource Selecting
. Обратитесь к руководству по программной установке значений параметров ObjectDataSource, чтобы освежить в памяти сведения о программном назначении значений параметрам ObjectDataSource.
В качестве альтернативы мы можем использовать ControlParameter и обратиться к свойству Suppliers
GridView SelectedValue
(см. рис. 19). Свойство GridView SelectedValue
возвращает значение, DataKey
соответствующее свойствуSelectedIndex
. Для того, чтобы этот вариант работал, нам нужно программно установить свойство GridView s SelectedIndex
на выбранную строку при ListProducts
нажатии на кнопку. В качестве дополнительного преимущества, при установке , SelectedIndex
выбранная запись примет значение, SelectedRowStyle
определенное в теме DataWebControls
(желтый фон).
Рисунок 19: Используйте параметр ControlParameter для указания выбранного значения GridView в качестве источника параметра (нажмите, чтобы просмотреть полноразмерное изображение)
После завершения работы мастера Visual Studio автоматически добавит поля для полей данных о продукте. Удалите все поля, ProductName
кроме , CategoryName
, и UnitPrice
BoundField, и измените HeaderText
свойства на Product, Category и Price.
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>
Чтобы выполнить это упражнение, нам нужно установить свойство GridView s SelectedIndex
в значение, а SelectedSuppliersIndex
свойство ProductsBySupplierPanel
Panel s Visible
— в положение True
при ListProducts
нажатии кнопки. Для этого создайте обработчик событий для ListProducts
события s Click
элемента управления Button Web и добавьте следующий код:
Protected Sub ListProducts_Click(sender As Object, e As EventArgs) _
Handles ListProducts.Click
' make sure one of the radio buttons has been selected
If SuppliersSelectedIndex < 0 Then
ChooseSupplierMsg.Visible = True
ProductsBySupplierPanel.Visible = False
Else
' Set the GridView's SelectedIndex
Suppliers.SelectedIndex = SuppliersSelectedIndex
' Show the ProductsBySupplierPanel panel
ProductsBySupplierPanel.Visible = True
End If
End Sub
Если поставщик не был выбран из GridView, метка отображается, ChooseSupplierMsg
а ProductsBySupplierPanel
панель скрывается. В противном случае, если поставщик был выбран, отображается и ProductsBySupplierPanel
обновляется свойство GridView SelectedIndex
.
На рисунке 20 показаны результаты после выбора поставщика Bigfoot Breweries и нажатия кнопки «Показать продукты на странице».
Рисунок 20: Продукты, поставляемые пивоварнями Bigfoot, перечислены на той же странице (Нажмите, чтобы просмотреть изображение в полном размере)
Сводка
Как обсуждалось в учебном пособии Master/Detail Using a Selectable Master GridView with a Details DetailView , записи могут быть выбраны из GridView с помощью CommandField, свойство которого ShowSelectButton
имеет значение True
. Но CommandField отображает свои кнопки в виде обычных кнопок, ссылок или изображений. Альтернативным вариантом пользовательского интерфейса для выбора строк является предоставление переключателя или флажка в каждой строке GridView. В этом уроке мы рассмотрели, как добавить колонку радиокнопок.
К сожалению, добавление колонки переключателей не так однозначно и просто, как можно было бы ожидать. Нет встроенного поля RadioButtonField, которое можно было бы добавить одним нажатием кнопки, а использование веб-элемента управления RadioButton в TemplateField создает свой собственный набор проблем. В конечном итоге, чтобы обеспечить такой интерфейс, нам приходится либо создавать пользовательский DataControlField
класс, либо прибегать к внедрению соответствующего HTML в TemplateField во время RowCreated
события.
Рассмотрев, как добавить столбец радиокнопок, обратим внимание на добавление столбца с флажками. С помощью столбца флажков пользователь может выбрать одну или несколько строк GridView, а затем выполнить некоторую операцию со всеми выбранными строками (например, выбрать набор сообщений электронной почты в веб-клиенте электронной почты, а затем удалить все выбранные письма). В следующем уроке мы увидим, как добавить такую колонку.
Счастливое программирование!
Сведения о авторе
Скотт Митчелл, автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга — Sams Teach Yourself ASP.NET 2.0 за 24 часа. С ним можно связаться по адресу mitchell@4GuysFromRolla.com.
Особое спасибо кому
Эта серия учебников была проверена многими полезными рецензентами. Ведущий рецензент для этого руководства был Дэвид Суру. Хотите просмотреть мои предстоящие статьи MSDN? Если да, напишите мне на mitchell@4GuysFromRolla.com.