Добавление столбца GridView переключателей (C#)
В этом руководстве рассматривается, как добавить столбец переключателей в элемент управления GridView, чтобы предоставить пользователю более интуитивно понятный способ выбора одной строки GridView.
Введение
Элемент управления GridView предлагает широкий набор встроенных функций. Он содержит ряд различных полей для отображения текста, изображений, гиперссылок и кнопок. Он поддерживает шаблоны для дальнейшей настройки. С помощью нескольких щелчков мыши можно создать GridView, в котором можно выбрать каждую строку с помощью кнопки, или включить возможности редактирования или удаления. Несмотря на множество предоставляемых функций, часто возникают ситуации, в которых потребуется добавить дополнительные, не поддерживаемые функции. В этом руководстве и в следующих двух мы рассмотрим, как расширить функциональные возможности GridView, чтобы включить в него дополнительные функции.
В этом и следующем руководстве основное внимание уделяется улучшению процесса выбора строк. Как описано в разделе Master/Details Using a Selectable Master GridView with a Details DetailsView , мы можем добавить CommandField в GridView, включающее кнопку Выбрать. При нажатии происходит обратная связь и свойство GridView обновляется до индекса строки, в которой была нажата SelectedIndex
кнопка "Выбрать". В учебнике Master/Detail Using a Selectable Master GridView with a DetailsView (Основные и подробные сведения) мы узнали, как использовать эту функцию для отображения сведений о выбранной строке GridView.
Хотя кнопка Выбрать работает во многих ситуациях, она может не работать в других ситуациях. Вместо использования кнопки для выбора обычно используются два других элемента пользовательского интерфейса: переключатель и флажок. Мы можем дополнить GridView, чтобы вместо кнопки Выбрать каждая строка содержала переключатель или флажок. В сценариях, когда пользователь может выбрать только одну из записей GridView, переключатель может быть предпочтительнее кнопки Выбрать. В ситуациях, когда пользователь может выбрать несколько записей, например в веб-приложении электронной почты, когда пользователю может потребоваться выбрать несколько сообщений, чтобы удалить флажок предлагает функции, недоступные в пользовательском интерфейсе кнопки "Выбрать" или переключателя.
В этом руководстве рассматривается добавление столбца переключателей в GridView. В этом руководстве рассматривается использование флажков.
Шаг 1. Создание усовершенствования веб-страниц GridView
Прежде чем мы начнем улучшать GridView, чтобы включить столбец переключателей, давайте сначала уделим немного времени, чтобы создать страницы ASP.NET в проекте веб-сайта, который нам понадобится для этого руководства и двух следующих двух. Начните с добавления новой папки с именем EnhancedGridView
. Затем добавьте в папку следующие страницы ASP.NET, чтобы связать каждую страницу со страницей Site.master
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
файл. В частности, добавьте следующую разметку после элемента управления Using the SqlDataSource :<siteMapNode>
<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 из панели элементов в Designer. Задайте для gridView s ID
значение Suppliers
и выберите из смарт-тега создать новый источник данных. В частности, создайте объект ObjectDataSource с именем SuppliersDataSource
, который извлекает данные из SuppliersBLL
объекта .
Рис. 4. Создание объекта ObjectDataSource с именем SuppliersDataSource
(щелкните для просмотра полноразмерного изображения)
Рис. 5. Настройка ObjectDataSource для использования SuppliersBLL
класса (щелкните для просмотра полноразмерного изображения)
Так как мы хотим перечислить только этих поставщиков в США, выберите GetSuppliersByCountry(country)
метод из раскрывающегося списка на вкладке SELECT.
Рис. 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
для этих двух кнопок ListProducts
и SendToProducts
, с идеей, что при ListProducts
нажатии будет происходить обратная связь и выбранные продукты поставщика будут перечислены на той же странице, но при SendToProducts
нажатии, пользователь будет взбит на другую страницу, которая перечисляет продукты.
На рисунке 9 показан элемент Suppliers
управления GridView и два элемента управления Button Web при просмотре в браузере.
Рис. 9. Эти поставщики из США указаны их имена, города и страны (щелкните для просмотра полноразмерного изображения)
Шаг 3. Добавление столбца переключателей
На этом этапе Suppliers
GridView содержит три Поля BoundField, отображающие название компании, город и страну каждого поставщика в США. Однако в нем по-прежнему отсутствует столбец переключателей. К сожалению, GridView не включает встроенный RadioButtonField, в противном случае мы могли бы просто добавить это в сетку и сделать. Вместо этого можно добавить TemplateField и настроить его ItemTemplate
для отрисовки переключателя, в результате чего для каждой строки GridView будет отображаться переключатель.
Изначально можно предположить, что требуемый пользовательский интерфейс можно реализовать путем добавления веб-элемента управления RadioButton в ItemTemplate
шаблон TemplateField. Хотя это действительно добавит один переключатель в каждую строку GridView, переключатели не могут быть сгруппированы и, следовательно, не являются взаимоисключающими. То есть конечный пользователь может одновременно выбрать несколько переключателей в GridView.
Несмотря на то, что использование TemplateField веб-элементов управления RadioButton не предоставляет необходимых функций, давайте реализуем этот подход, так как стоит изучить, почему результирующие переключатели не группируются. Для начала добавьте TemplateField в Элемент Управления GridView поставщиков, сделав его крайним левым полем. Затем в смарт-теге GridView щелкните ссылку Изменить шаблоны и перетащите веб-элемент управления RadioButton из панели элементов в TemplateField ( ItemTemplate
см. рис. 10). Присвойте свойству RadioButton значение ID
, RowSelector
а свойству GroupName
— значение SuppliersGroup
.
Рис. 10. Добавление веб-элемента управления RadioButton в ItemTemplate
(Щелкните для просмотра полноразмерного изображения)
После внесения этих дополнений с помощью Designer разметка 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 s GroupName
используется для группировки ряда переключателей. Все элементы управления RadioButton с одинаковым GroupName
значением считаются сгруппированы; одновременно из группы можно выбрать только один переключатель. Свойство GroupName
задает значение атрибута отображаемого переключателя name
. Браузер проверяет атрибуты переключателей name
, чтобы определить группирование переключателей.
После добавления веб-элемента управления RadioButton в ItemTemplate
, перейдите на эту страницу в браузере и щелкните переключатели в строках сетки. Обратите внимание, что переключатели не сгруппированы, что позволяет выбрать все строки, как показано на рисунке 11.
Рис. 11. Переключатели GridView не сгруппированы (щелкните для просмотра полноразмерного изображения)
Причина, по которой переключатели не группируются, заключается в том, что их отображаемые 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
элементами родительских переключателей, элементов управления ID
GridViewRow
GridViewID
, элементов управления ID
контентом и веб-формы ID
. Эти ID
значения добавляются таким образом, чтобы каждый отображаемый веб-элемент управления в GridView был уникальным name
id
.
Каждый отрисованный элемент управления нуждается в своем, name
id
так как браузер уникально идентифицирует каждый элемент управления на стороне клиента и как он определяет веб-сервер, какое действие или изменение произошло при обратной отправке. Например, представьте, что мы хотим выполнить код на стороне сервера при каждом изменении проверенного состояния RadioButton. Это можно сделать, задав свойству RadioButton s AutoPostBack
значение true
и создав обработчик CheckChanged
события. Однако если отображаемые name
значения и id
для всех переключателей были одинаковыми, при обратной отправке мы не могли определить, какой конкретный элемент RadioButton был нажат.
Кроме того, мы не можем создать столбец переключателей в GridView с помощью веб-элемента управления RadioButton. Вместо этого мы должны использовать довольно архаические методы, чтобы убедиться, что соответствующая разметка внедряется в каждую строку GridView.
Примечание
Как и элемент управления RadioButton Web, элемент управления HTML переключателя при добавлении в шаблон будет содержать уникальный name
атрибут, что делает переключатели в сетке разгруппированы. Если вы не знакомы с элементами управления HTML, не стесняйтесь игнорировать это примечание, так как элементы управления HTML используются редко, особенно в ASP.NET 2.0. Но если вы хотите узнать больше, см. запись блога К. Скотта АлленаВеб-элементы управления и элементы управления HTML.
Использование литерального элемента управления для внедрения разметки переключателя
Чтобы правильно сгруппировать все переключатели в GridView, необходимо вручную внедрить разметку переключателей в ItemTemplate
. Каждому переключателю требуется один и тот же name
атрибут, но он должен иметь уникальный id
атрибут (на случай, если мы хотим получить доступ к переключателю с помощью клиентского скрипта). После того как пользователь выберет переключатель и отправит назад страницу, браузер отправит обратно значение атрибута выбранного переключателя value
. Поэтому каждому переключателю потребуется уникальный value
атрибут. Наконец, при обратной отправке необходимо добавить checked
атрибут к одному выбранному переключателю. В противном случае после того, как пользователь сделает выбор и снова сделает запись, переключатели вернутся в состояние по умолчанию (все не выбраны).
Существует два подхода, которые можно использовать для внедрения низкоуровневой разметки в шаблон. Одним из них является сочетание разметки и вызовов методов форматирования, определенных в классе кода программной части. Этот метод был впервые рассмотрен в руководстве по использованию templateFields в руководстве по элементу управления GridView . В нашем случае это может выглядеть примерно так:
<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>'
name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />
Здесь и GetRadioButtonValue
будут методами, определенными в классе кода программной части, GetUniqueRadioButton
который возвращает соответствующие id
значения и value
значения атрибутов для каждого переключателя. Этот подход хорошо подходит для назначения id
атрибутов и value
, но не соответствует значению checked
атрибута, так как синтаксис привязки данных выполняется только при первой привязке данных к GridView. Таким образом, если в GridView включено состояние представления, методы форматирования будут запускаться только при первой загрузке страницы (или при явном восстановлении GridView к источнику данных), и поэтому функция, задающая checked
атрибут, не будет вызываться при обратной отправке. Это довольно тонкая проблема и немного за область этой статьи, так что я оставлю его на этом. Я, однако, призываю вас попробовать использовать приведенный выше подход и проработать его до точки, где вы получите застрял. Хотя такое упражнение не поможет вам приблизиться к рабочей версии, оно поможет лучше понять GridView и жизненный цикл привязки данных.
Другой подход к внедрению пользовательской низкоуровневой разметки в шаблон и подход, который мы будем использовать в этом руководстве, заключается в добавлении в шаблон элемента управления Литерал . Затем в обработчике событий GridView RowCreated
или RowDataBound
можно получить программный доступ к элементу управления Литерал, а его Text
свойству присвоено значение разметки для выдачи.
Начните с удаления элемента RadioButton из templateField s ItemTemplate
, заменив его элементом управления Литерал. Присвойте элементу управления Литерал значение ID
RadioButtonMarkup
.
Рис. 12. Добавление элемента управления "Литерал" в ItemTemplate
(щелкните для просмотра полноразмерного изображения)
Затем создайте обработчик событий для события GridView RowCreated
. Событие RowCreated
срабатывает один раз для каждой добавленной строки, независимо от того, выполняется ли отскок данных в GridView. Это означает, что даже при обратной отправке, когда данные перезагружаются из состояния представления, событие по-прежнему срабатывает, и именно поэтому мы используем его вместо RowDataBound
(который срабатывает только в том случае, RowCreated
если данные явно привязаны к веб-элементу управления данными).
В этом обработчике событий мы хотим продолжить только в том случае, если мы имеем дело со строкой данных. Для каждой строки данных мы хотим программно ссылаться на 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
обработчиках событий для веб-элементов управления Button, давайте добавим 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 (вместо того, чтобы переключатели не были выбраны по умолчанию, что является текущим поведением). Чтобы первый переключатель был выбран по умолчанию, просто измените if (SuppliersSelectedIndex == e.Row.RowIndex)
оператор на следующий: if (SuppliersSelectedIndex == e.Row.RowIndex || (!Page.IsPostBack && e.Row.RowIndex == 0))
.
На этом этапе мы добавили столбец сгруппированных переключателей в 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 и SendToProducts
. При нажатии кнопки SendToProducts
мы хотим отправить пользователя в ~/Filtering/ProductsForSupplierDetails.aspx
. Эта страница была создана в учебнике Фильтрация основных и подробных данных на двух страницах и отображает продукты для поставщика, передаваемые SupplierID
через поле querystring с именем SupplierID
.
Чтобы предоставить эту функцию, создайте обработчик событий для SendToProducts
события Button Click
. На шаге 3 мы добавили SuppliersSelectedIndex
свойство , которое возвращает индекс строки, для которой выбран переключатель. Соответствующий SupplierID
объект можно получить из коллекции GridView 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 не выбраны переключатели и пользователь нажимает кнопку , будет иметь -1
значение , что приведет к возникновению исключения, так как -1
находится за пределы SendToProducts
диапазона индексов DataKeys
SuppliersSelectedIndex
коллекции. Однако это не касается, если вы решили обновить RowCreated
обработчик событий, как описано на шаге 3, чтобы сначала был выбран первый переключатель в GridView.
Чтобы вместить SuppliersSelectedIndex
значение -1
, добавьте элемент управления Label Web на страницу над GridView. Присвойте свойству ID
ChooseSupplierMsg
значение , свойству EnableViewState
CssClass
Warning
и Visible
свойству false
значение , а свойству — значение , а свойству Text
— значение Выберите поставщика из сетки. Класс Warning
CSS отображает текст красным, курсивным, полужирным, крупным шрифтом и определяется в Styles.css
. Если задать EnableViewState
для свойств и Visible
значение false
, метка не отображается, за исключением тех обратных передач, где свойству элемента управления Visible
программно задано значение true
.
Рис. 13. Добавление веб-элемента управления Метка над 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
отображается, если поставщик не выбран (щелкните для просмотра полноразмерного изображения)
Рис. 15. Продукты выбранного поставщика отображаются в ProductsForSupplierDetails.aspx
(щелкните, чтобы просмотреть полноразмерное изображение)
Шаг 5. Отображение продуктов выбранного поставщика на той же странице
На шаге 4 мы узнали, как отправить пользователя на другую веб-страницу для отображения продуктов выбранного поставщика. Кроме того, выбранные продукты поставщика могут отображаться на той же странице. Чтобы проиллюстрировать это, мы добавим еще один элемент GridView для RadioButtonField.aspx
отображения продуктов выбранного поставщика.
Так как мы хотим, чтобы этот элемент GridView продуктов отображался только после выбора поставщика, добавьте веб-элемент управления Панель под Suppliers
GridView, задав для него ID
значение ProductsBySupplierPanel
, а свойству Visible
— значение false
. На панели добавьте текст Products for the Selected Supplier (Продукты для выбранного поставщика), а затем GridView с именем ProductsBySupplier
. В смарт-теге GridView выберите привязку к новому объекту ObjectDataSource с именем ProductsBySupplierDataSource
.
Рис. 16. Привязка ProductsBySupplier
GridView к новому объекту ObjectDataSource (щелкните для просмотра полноразмерного изображения)
Затем настройте ObjectDataSource для использования ProductsBLL
класса . Так как мы хотим получить только те продукты, которые предоставляются выбранным поставщиком, укажите, что ObjectDataSource должен вызывать GetProductsBySupplierID(supplierID)
метод для получения его данных. Выберите (Нет) в раскрывающихся списках на вкладках UPDATE, INSERT и DELETE.
Рис. 17. Настройка ObjectDataSource для использования GetProductsBySupplierID(supplierID)
метода (щелкните для просмотра полноразмерного изображения)
Рис. 18. Задайте для Drop-Down Списки значение (Нет) на вкладках UPDATE, INSERT и DELETE (щелкните для просмотра полноразмерного изображения)
Настроив вкладки SELECT, UPDATE, INSERT и DELETE, нажмите кнопку Далее. GetProductsBySupplierID(supplierID)
Так как метод ожидает входной параметр, мастер создания источника данных предлагает указать источник для значения параметра.
У нас есть несколько вариантов указания источника значения параметра. Можно использовать объект Parameter по умолчанию и программно присвоить значение SuppliersSelectedIndex
свойства свойству Parameters DefaultValue
в обработчике Selecting
событий ObjectDataSource. Вернитесь к учебнику Программное задание значений параметров ObjectDataSource , чтобы ознакомиться с программным назначением значений для параметров ObjectDataSource.
Кроме того, можно использовать ControlParameter и ссылаться на Suppliers
свойство GridView (SelectedValue
см. рис. 19). Свойство GridView SelectedValue
возвращает значение, DataKey
соответствующее свойствуSelectedIndex
. Чтобы этот параметр работал, необходимо программно задать для свойства GridView SelectedIndex
значение выбранной строки при нажатии кнопки ListProducts
. В качестве дополнительного преимущества, задав SelectedIndex
, выбранная запись примет на SelectedRowStyle
себя значение, определенное DataWebControls
в теме (желтый фон).
Рис. 19. Использование controlParameter для указания selectedValue gridView s в качестве источника параметров (щелкните, чтобы просмотреть полноразмерное изображение)
После завершения работы мастера Visual Studio автоматически добавит поля для полей данных продукта. Удалите все поля, кроме ProductName
, CategoryName
и UnitPrice
BoundFields, а затем измените 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 SelectedIndex
значение , SelectedSuppliersIndex
а свойству ProductsBySupplierPanel
Panel Visible
— значение true
при нажатии ListProducts
кнопки. Для этого создайте обработчик событий для ListProducts
события элемента управления Click
Button Web и добавьте следующий код:
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 SelectedIndex
.
На рисунке 20 показаны результаты после выбора поставщика "Пивоварни снежного человека" и нажатия кнопки "Показать продукты на странице".
Рис. 20. Продукты, предоставляемые пивоваренными компаниями снежного человека, перечислены на той же странице (щелкните, чтобы просмотреть полноразмерное изображение)
Сводка
Как описано в учебнике 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, а затем выполнить некоторые операции со всеми выбранными строками (например, выбрать набор сообщений электронной почты из веб-клиента электронной почты, а затем удалить все выбранные сообщения электронной почты). В следующем руководстве мы посмотрим, как добавить такой столбец.
Счастливое программирование!
Об авторе
Скотт Митчелл (Scott Mitchell), автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с Веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 2.0 в 24 часа. Его можно связать по адресу mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.
Отдельная благодарность
Эта серия учебников была проверена многими полезными рецензентами. Ведущим рецензентом этого руководства был Дэвид Суру. Хотите ознакомиться с моими предстоящими статьями MSDN? Если да, опустите мне строку в mitchell@4GuysFromRolla.com.