Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Хотя элемент управления GridView не предоставляет встроенную поддержку вставки новой записи данных, в этом руководстве показано, как расширить GridView для включения интерфейса вставки.
Введение
Как описано в руководстве по вставке, обновлению и удалению данных , элементы управления GridView, DetailsView и FormView Web включают встроенные возможности изменения данных. При использовании с декларативными элементами управления источниками данных эти три веб-элемента управления можно быстро и легко настроить для изменения данных и в сценариях без необходимости писать одну строку кода. К сожалению, только элементы управления DetailsView и FormView предоставляют встроенные возможности вставки, редактирования и удаления. GridView предлагает только поддержку редактирования и удаления. Тем не менее, приложив немного усилий, мы можем усовершенствовать GridView, чтобы включить интерфейс вставки.
При добавлении возможностей вставки в GridView мы отвечаем за решение о том, как будут добавляться новые записи, создавать интерфейс вставки и писать код для вставки новой записи. В этом руководстве мы рассмотрим, как добавить интерфейс вставки в строку нижнего колонтитула GridView (см. рис. 1). Ячейка футера для каждого столбца включает соответствующий элемент пользовательского интерфейса для сбора данных (текстовое поле для имени продукта, выпадающий список для поставщика и т. д.). Нам также нужен столбец для кнопки "Добавить", которая при нажатии приведет к обратной отправке и вставке новой записи в Products
таблицу с использованием значений, предоставленных в строке нижнего колонтитула.
Рис. 1. Строка нижнего колонтитула предоставляет интерфейс для добавления новых продуктов (щелкните, чтобы просмотреть изображение полного размера)
Шаг 1. Отображение сведений о продукте в GridView
Прежде чем мы займемся созданием интерфейса вставки в нижней части GridView, давайте сначала сосредоточимся на добавлении GridView на страницу для отображения продуктов из базы данных. Начните с открытия InsertThroughFooter.aspx
страницы в EnhancedGridView
папке и перетащите GridView из панели элементов в конструктор, установив для свойства GridView ID
значение Products
. Затем используйте смарт-тег GridView, чтобы привязать его к новому объекту ObjectDataSource с именем ProductsDataSource
.
Рис. 2. Создайте новый объект ObjectDataSource с именем ProductsDataSource
(Щелкните, чтобы просмотреть изображение в полном размере)
Настройте ObjectDataSource для использования метода ProductsBLL
класса GetProducts()
для получения сведений о продукте. В этом руководстве мы сосредоточимся строго на добавлении функций вставки и не будем беспокоиться о редактировании и удалении. Поэтому убедитесь, что в раскрывающемся списке на вкладке INSERT задано AddProduct()
значение, а в раскрывающихся списках на вкладках UPDATE и DELETE задано значение (Нет).
Рис. 3. Сопоставление AddProduct
метода с методом ObjectDataSource Insert()
(щелкните, чтобы просмотреть изображение полного размера)
Рис. 4. Установите вкладки UPDATE и DELETE списков Drop-Down на (нет) (щелкните, чтобы просмотреть изображение полного размера)
После завершения мастера настройки источника данных ObjectDataSource Visual Studio автоматически добавит поля в GridView для каждого из соответствующих полей данных. Теперь оставьте все поля, добавленные Visual Studio. Позже в этом руководстве мы вернемся и удалим некоторые поля, значения которых не нужно указывать при добавлении новой записи.
Так как в базе данных есть около 80 продуктов, пользователю потребуется прокрутить весь путь вниз до нижней части веб-страницы, чтобы добавить новую запись. Таким образом, позвольте включить разбиение по страницам, чтобы сделать вставляющий интерфейс более видимым и доступным. Чтобы включить разбиение по страницам, просто установите флажок "Включить разбиение по страницам" в смарт-теге GridView.
На этом этапе декларативная разметка GridView и ObjectDataSource должны выглядеть следующим образом:
<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ProductsDataSource"
AllowPaging="True" EnableViewState="False">
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="ProductID"
InsertVisible="False" ReadOnly="True"
SortExpression="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName"
SortExpression="ProductName" />
<asp:BoundField DataField="SupplierID" HeaderText="SupplierID"
SortExpression="SupplierID" />
<asp:BoundField DataField="CategoryID" HeaderText="CategoryID"
SortExpression="CategoryID" />
<asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit"
SortExpression="QuantityPerUnit" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock"
SortExpression="UnitsInStock" />
<asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder"
SortExpression="UnitsOnOrder" />
<asp:BoundField DataField="ReorderLevel" HeaderText="ReorderLevel"
SortExpression="ReorderLevel" />
<asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
SortExpression="Discontinued" />
<asp:BoundField DataField="CategoryName" HeaderText="CategoryName"
ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="SupplierName" HeaderText="SupplierName"
ReadOnly="True" SortExpression="SupplierName" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
InsertMethod="AddProduct" OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProducts" TypeName="ProductsBLL">
<InsertParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="supplierID" Type="Int32" />
<asp:Parameter Name="categoryID" Type="Int32" />
<asp:Parameter Name="quantityPerUnit" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="unitsInStock" Type="Int16" />
<asp:Parameter Name="unitsOnOrder" Type="Int16" />
<asp:Parameter Name="reorderLevel" Type="Int16" />
<asp:Parameter Name="discontinued" Type="Boolean" />
</InsertParameters>
</asp:ObjectDataSource>
Рис. 5. Все поля данных продукта отображаются в paged GridView (щелкните, чтобы просмотреть изображение полного размера)
Шаг 2. Добавление строки нижнего колонтитула
Вместе со строками заголовков и данных GridView включает в себя строку нижнего колонтитула. Строки верхнего и нижнего колонтитулов отображаются в зависимости от значений свойств ShowHeader
и ShowFooter
GridView. Чтобы отобразить нижний колонтитул, просто задайте свойству ShowFooter
значение true
. Как показано на рисунке 6, установка свойства ShowFooter
в true
добавляет строку нижнего колонтитула в сетку.
Рис. 6. Чтобы отобразить строку нижнего колонтитула, установите ShowFooter
в True
(щелкните, чтобы просмотреть изображение в полном размере)
Обратите внимание, что нижний колонтитул имеет темно-красный фон. Это связано с темой DataWebControls, которую мы создали и применили ко всем страницам в руководстве по отображению данных с помощью ObjectDataSource . В частности, GridView.skin
файл настраивает FooterStyle
свойство так, чтобы использовался FooterStyle
класс CSS. Класс FooterStyle
определяется Styles.css
следующим образом:
.FooterStyle
{
background-color: #a33;
color: White;
text-align: right;
}
Замечание
Мы рассматривали использование подвальной строки GridView в предыдущих руководствах. При необходимости вернитесь к разделу Отображение сводной информации в нижнем колонтитуле GridView для освежения памяти.
После задания свойства ShowFooter
на true
, уделите время, чтобы просмотреть выходные данные в браузере. В настоящее время строка нижнего колонтитула не содержит текста или веб-элементов управления. На шаге 3 мы изменим нижний колонтитул для каждого поля GridView, чтобы он включает соответствующий интерфейс вставки.
Рис. 7. Пустая строка нижнего колонтитула отображается над элементами управления интерфейсом разбиения на страницы (щелкните, чтобы просмотреть изображение полного размера)
Шаг 3. Настройка строки нижнего колонтитула
В руководстве по элементу управления GridView мы узнали, как значительно настроить отображение определенного столбца GridView с помощью TemplateFields (в отличие от BoundFields или CheckBoxFields); При настройке интерфейса изменения данных мы рассмотрели использование TemplateFields для настройки интерфейса редактирования в GridView. Помните, что TemplateField состоит из ряда шаблонов, определяющих сочетание разметки, веб-элементов управления и синтаксиса привязки данных, используемого для определенных типов строк.
ItemTemplate
Например, задает шаблон, используемый для строк, доступных только для чтения, а EditItemTemplate
шаблон определяется для редактируемой строки.
Наряду с ItemTemplate
и EditItemTemplate
, TemplateField также включает FooterTemplate
, которое определяет содержимое строки нижнего колонтитула. Поэтому можно добавить веб-элементы управления, необходимые для каждого поля интерфейса вставки в FooterTemplate
. Чтобы начать, преобразуйте все поля в GridView в TemplateFields. Это можно сделать, щелкнув ссылку "Изменить столбцы" в смарт-теге GridView, выбрав каждое поле в левом нижнем углу и нажав кнопку "Преобразовать это поле в ссылку TemplateField".
Рис. 8. Преобразование каждого поля в templateField
Нажав на «Преобразовать это поле в TemplateField», текущий тип поля изменится на эквивалентный TemplateField. Например, каждый BoundField заменяется TemplateField, в котором ItemTemplate
содержит метку, отображающую соответствующее поле данных, а EditItemTemplate
отображает поле данных в текстовом поле.
ProductName
BoundField был преобразован в следующую разметку TemplateField:
<asp:TemplateField HeaderText="ProductName" SortExpression="ProductName">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server"
Text='<%# Bind("ProductName") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server"
Text='<%# Bind("ProductName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Подобно тому, как Discontinued
CheckBoxField был преобразован в TemplateField, в котором ItemTemplate
и EditItemTemplate
содержат веб-элемент управления CheckBox (с отключенным флажком ItemTemplate
). Приложение BoundField только для ProductID
чтения было преобразовано в TemplateField с элементом управления Label в обоих ItemTemplate
и EditItemTemplate
. Короче говоря, преобразование существующего поля GridView в TemplateField — это быстрый и простой способ переключиться на более настраиваемый TemplateField, не теряя ни одной из существующих функций поля.
Так как GridView, с которым мы работаем, не поддерживает редактирование, вы можете удалить EditItemTemplate
из каждого TemplateField, оставив только ItemTemplate
. После этого декларативная разметка GridView должна выглядеть следующим образом:
<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ProductsDataSource"
AllowPaging="True" EnableViewState="False" ShowFooter="True">
<Columns>
<asp:TemplateField HeaderText="ProductID" InsertVisible="False"
SortExpression="ProductID">
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text='<%# Bind("ProductID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="ProductName" SortExpression="ProductName">
<ItemTemplate>
<asp:Label ID="Label2" runat="server"
Text='<%# Bind("ProductName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="SupplierID" SortExpression="SupplierID">
<ItemTemplate>
<asp:Label ID="Label3" runat="server"
Text='<%# Bind("SupplierID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="CategoryID" SortExpression="CategoryID">
<ItemTemplate>
<asp:Label ID="Label4" runat="server"
Text='<%# Bind("CategoryID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="QuantityPerUnit"
SortExpression="QuantityPerUnit">
<ItemTemplate>
<asp:Label ID="Label5" runat="server"
Text='<%# Bind("QuantityPerUnit") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="UnitPrice" SortExpression="UnitPrice">
<ItemTemplate>
<asp:Label ID="Label6" runat="server"
Text='<%# Bind("UnitPrice") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="UnitsInStock"
SortExpression="UnitsInStock">
<ItemTemplate>
<asp:Label ID="Label7" runat="server"
Text='<%# Bind("UnitsInStock") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="UnitsOnOrder"
SortExpression="UnitsOnOrder">
<ItemTemplate>
<asp:Label ID="Label8" runat="server"
Text='<%# Bind("UnitsOnOrder") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="ReorderLevel"
SortExpression="ReorderLevel">
<ItemTemplate>
<asp:Label ID="Label9" runat="server"
Text='<%# Bind("ReorderLevel") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Discontinued"
SortExpression="Discontinued">
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server"
Checked='<%# Bind("Discontinued") %>' Enabled="false" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="CategoryName"
SortExpression="CategoryName">
<ItemTemplate>
<asp:Label ID="Label10" runat="server"
Text='<%# Bind("CategoryName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="SupplierName"
SortExpression="SupplierName">
<ItemTemplate>
<asp:Label ID="Label11" runat="server"
Text='<%# Bind("SupplierName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Теперь, когда каждое поле GridView было преобразовано в TemplateField, мы можем ввести соответствующий интерфейс вставки в каждое поле FooterTemplate
. Некоторые поля не будут иметь интерфейс вставки (ProductID
например, например), другие будут отличаться в веб-элементах управления, используемых для сбора сведений о новом продукте.
Чтобы создать интерфейс редактирования, выберите ссылку "Изменить шаблоны" из смарт-тега GridView. Затем в раскрывающемся списке выберите соответствующее поле FooterTemplate
и перетащите нужный элемент управления из панели инструментов в конструктор.
Рис. 9. Добавление соответствующего интерфейса вставки в каждое поле FooterTemplate
(щелкните, чтобы просмотреть изображение полного размера)
Следующий маркированный список перечисляет поля GridView, указывая интерфейс вставки для добавления:
-
ProductID
никакой. -
ProductName
добавьте текстовое поле и задайте для нее значениеID
NewProductName
. Добавьте элемент управления RequiredFieldValidator, чтобы убедиться, что пользователь вводит значение для имени нового продукта. -
SupplierID
никакой. -
CategoryID
никакой. -
QuantityPerUnit
добавьте текстовое поле, задав для нее значениеID
NewQuantityPerUnit
. -
UnitPrice
добавьте TextBox с именемNewUnitPrice
и CompareValidator, который гарантирует, что введенное значение является значением в валюте, больше или равно нулю. -
UnitsInStock
используйте TextBox, для которогоID
задано значениеNewUnitsInStock
. Включите CompareValidator, который гарантирует, что введенное значение является целым числом больше или равно нулю. -
UnitsOnOrder
используйте TextBox, для которогоID
задано значениеNewUnitsOnOrder
. Включите CompareValidator, который гарантирует, что введенное значение является целым числом больше или равно нулю. -
ReorderLevel
используйте TextBox, для которогоID
задано значениеNewReorderLevel
. Включите CompareValidator, который гарантирует, что введенное значение является целым числом больше или равно нулю. -
Discontinued
добавьте флажок, установив егоID
наNewDiscontinued
. -
CategoryName
добавьте DropDownList и установите ееID
наNewCategoryID
. Привяжите его к новому объекту данных ObjectDataSource с именемCategoriesDataSource
и настройте его для использования методаCategoriesBLL
классаGetCategories()
. Сделайте так, чтобы раскрывающийся списокListItem
отображал поле данныхCategoryName
, используя поле данныхCategoryID
в качестве их значений. -
SupplierName
добавьте DropDownList и установите ееID
наNewSupplierID
. Привяжите его к новому объекту данных ObjectDataSource с именемSuppliersDataSource
и настройте его для использования методаSuppliersBLL
классаGetSuppliers()
. Сделайте так, чтобы раскрывающийся списокListItem
отображал поле данныхCompanyName
, используя поле данныхSupplierID
в качестве их значений.
Для каждого элемента управления проверки удалите ForeColor
свойство, чтобы FooterStyle
цвет белого переднего плана класса CSS использовался вместо красного цвета по умолчанию. Также используйте ErrorMessage
свойство для подробного описания, но присвойте Text
свойству звездочку. Чтобы предотвратить перенос текста элемента управления проверки, вызывающий перенос интерфейса вставки на две строки, установите для свойства FooterStyle
значение false у каждого из Wrap
, которые используют элемент управления проверки. Наконец, добавьте элемент управления ValidationSummary под GridView и задайте для свойства ShowMessageBox
значение true
, а для свойства ShowSummary
значение false
.
При добавлении нового продукта необходимо предоставить CategoryID
и SupplierID
. Сведения записываются в раскрывающихся списках в ячейках нижнего колонтитула для полей CategoryName
и SupplierName
. Я решил использовать эти поля вместо CategoryID
и SupplierID
TemplateFields, потому что в данных строках сетки пользователь, вероятно, больше заинтересован в просмотре имен категорий и поставщиков, а не их идентификаторов.
CategoryID
Так как теперь значения SupplierID
и CategoryName
записываются в интерфейсы вставки полей SupplierName
, можно удалить CategoryID
и SupplierID
TemplateFields из GridView.
Аналогичным образом, ProductID
не используется при добавлении нового продукта, поэтому ProductID
TemplateField также можно удалить. Однако давайте оставим ProductID
поле в сетке. Помимо элементов управления TextBoxes, DropDownLists, CheckBoxes и проверки, составляющих интерфейс вставки, нам также потребуется кнопка "Добавить", которая при нажатии выполняет логику для добавления нового продукта в базу данных. На шаге 4 мы добавим кнопку "Добавить" в интерфейс вставки в ProductID
TemplateField FooterTemplate
.
Вы можете улучшить внешний вид различных полей GridView. Например, может потребоваться отформатировать UnitPrice
значения в виде валюты, выровнять по правому краю поля UnitsInStock
, UnitsOnOrder
и ReorderLevel
, а также обновить HeaderText
значения для TemplateFields.
После создания множества интерфейсов вставки в FooterTemplate
, удаления SupplierID
, CategoryID
TemplateFields и улучшения эстетики сетки путем форматирования и выравнивания TemplateFields, декларативная разметка GridView должна выглядеть следующим образом:
<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ProductsDataSource"
AllowPaging="True" EnableViewState="False" ShowFooter="True">
<Columns>
<asp:TemplateField HeaderText="ProductID" InsertVisible="False"
SortExpression="ProductID">
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text='<%# Bind("ProductID") %>'></asp:Label>
</ItemTemplate>
<ItemStyle HorizontalAlign="Center" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Product" SortExpression="ProductName">
<ItemTemplate>
<asp:Label ID="Label2" runat="server"
Text='<%# Bind("ProductName") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="NewProductName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" ControlToValidate="NewProductName"
Display="Dynamic" ForeColor="
ErrorMessage="You must enter a name for the new product.">
* </asp:RequiredFieldValidator>
</FooterTemplate>
<FooterStyle Wrap="False" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Category" SortExpression="CategoryName">
<ItemTemplate>
<asp:Label ID="Label10" runat="server"
Text='<%# Bind("CategoryName") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:DropDownList ID="NewCategoryID" runat="server"
DataSourceID="CategoriesDataSource"
DataTextField="CategoryName" DataValueField="CategoryID">
</asp:DropDownList>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Supplier" SortExpression="SupplierName">
<ItemTemplate>
<asp:Label ID="Label11" runat="server"
Text='<%# Bind("SupplierName") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:DropDownList ID="NewSupplierID" runat="server"
DataSourceID="SuppliersDataSource"
DataTextField="CompanyName" DataValueField="SupplierID">
</asp:DropDownList><asp:ObjectDataSource ID="SuppliersDataSource"
runat="server" OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
</asp:ObjectDataSource>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Qty/Unit" SortExpression="QuantityPerUnit">
<ItemTemplate>
<asp:Label ID="Label5" runat="server"
Text='<%# Bind("QuantityPerUnit") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="NewQuantityPerUnit" runat="server"></asp:TextBox>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Price" SortExpression="UnitPrice">
<ItemTemplate>
<asp:Label ID="Label6" runat="server"
Text='<%# Bind("UnitPrice", "{0:c}") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
$<asp:TextBox ID="NewUnitPrice" runat="server" Columns="8" />
<asp:CompareValidator ID="CompareValidator1" runat="server"
ControlToValidate="NewUnitPrice"
ErrorMessage="You must enter a valid currency value greater than
or equal to 0.00. Do not include the currency symbol."
ForeColor="" Operator="GreaterThanEqual" Type="Currency"
ValueToCompare="0" Display="Dynamic">
* </asp:CompareValidator>
</FooterTemplate>
<ItemStyle HorizontalAlign="Right" />
<FooterStyle Wrap="False" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Units In Stock"
SortExpression="Units In Stock">
<ItemTemplate>
<asp:Label ID="Label7" runat="server"
Text='<%# Bind("UnitsInStock") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="NewUnitsInStock" runat="server" Columns="5" />
<asp:CompareValidator ID="CompareValidator2" runat="server"
ControlToValidate="NewUnitsInStock" Display="Dynamic"
ErrorMessage="You must enter a valid numeric value for units
in stock that's greater than or equal to zero."
ForeColor="" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0">*</asp:CompareValidator>
</FooterTemplate>
<ItemStyle HorizontalAlign="Right" />
<FooterStyle Wrap="False" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Units On Order" SortExpression="UnitsOnOrder">
<ItemTemplate>
<asp:Label ID="Label8" runat="server"
Text='<%# Bind("UnitsOnOrder") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="NewUnitsOnOrder" runat="server" Columns="5" />
<asp:CompareValidator ID="CompareValidator3" runat="server"
ControlToValidate="NewUnitsOnOrder" Display="Dynamic"
ErrorMessage="You must enter a valid numeric value for units on
order that's greater than or equal to zero."
ForeColor="" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0">*</asp:CompareValidator>
</FooterTemplate>
<ItemStyle HorizontalAlign="Right" />
<FooterStyle Wrap="False" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Reorder Level" SortExpression="ReorderLevel">
<ItemTemplate>
<asp:Label ID="Label9" runat="server"
Text='<%# Bind("ReorderLevel") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="NewReorderLevel" runat="server" Columns="5" />
<asp:CompareValidator ID="CompareValidator4" runat="server"
ControlToValidate="NewReorderLevel" Display="Dynamic"
ErrorMessage="You must enter a valid numeric value for reorder
level that's greater than or equal to zero."
ForeColor="" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0">*</asp:CompareValidator>
</FooterTemplate>
<ItemStyle HorizontalAlign="Right" />
<FooterStyle Wrap="False" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server"
Checked='<%# Bind("Discontinued") %>' Enabled="false" />
</ItemTemplate>
<FooterTemplate>
<asp:CheckBox ID="NewDiscontinued" runat="server" />
</FooterTemplate>
<ItemStyle HorizontalAlign="Center" />
<FooterStyle HorizontalAlign="Center" />
</asp:TemplateField>
</Columns>
</asp:GridView>
При просмотре в браузере строка нижнего колонтитула GridView теперь включает завершенный интерфейс вставки данных (см. рис. 10). На этом этапе интерфейс вставки не включает средства для пользователя, чтобы указать, что она ввела данные для нового продукта и хочет вставить новую запись в базу данных. Кроме того, мы еще не рассмотрели, как данные, введенные в нижний колонтитул, будут преобразовываться в новую запись в Products
базе данных. На шаге 4 мы рассмотрим, как включить кнопку "Добавить" в интерфейс вставки и как выполнить код на этапе возврата данных при нажатии. На шаге 5 показано, как вставить новую запись с помощью данных из нижнего колонтитула.
Рис. 10. Нижний колонтитул GridView предоставляет интерфейс для добавления новой записи (щелкните, чтобы просмотреть изображение полного размера)
Шаг 4. Включение кнопки "Добавить" в интерфейс вставки
Нам нужно включить кнопку "Добавить" где-то в интерфейсе добавления, так как в настоящее время интерфейс вставки строчки нижнего колонтитула не имеет возможности для пользователя указать, что он завершил ввод информации о новом продукте. Это можно поместить в один из существующих элементов FooterTemplate
или добавить новый столбец в сетку для этой цели. В этом руководстве давайте поместим кнопку "Добавить" в ProductID
файле FooterTemplate
TemplateField.
В Дизайнере щелкните ссылку "Изменить шаблоны" в смарт-теге GridView'а и выберите ProductID
поля FooterTemplate
из раскрывающегося списка. Добавьте элемент управления Web (или LinkButton или ImageButton, если вы предпочитаете) в шаблон, присвойте ему идентификатор AddProduct
, установите значение CommandName
на Insert и его свойство Text
на Add, как показано на рисунке 11.
Рис. 11. Поместите кнопку "Добавить" в ProductID
templateField s FooterTemplate
(щелкните, чтобы просмотреть изображение полного размера)
После включения кнопки "Добавить" проверьте страницу в браузере. Обратите внимание, что при нажатии кнопки "Добавить" с недопустимыми данными в интерфейсе вставки, процесс обратной передачи данных прерывается, и элемент управления ValidationSummary указывает на недопустимые данные (см. рис. 12). При вводе соответствующих данных нажатие кнопки "Добавить" приводит к обратной отправке. Однако запись не добавляется в базу данных. Нам потребуется написать немного кода, чтобы действительно выполнить вставку.
Рис. 12. Обратная связь кнопки "Добавить" является короткой, если в интерфейсе вставки есть недопустимые данные (щелкните, чтобы просмотреть изображение полного размера)
Замечание
Элементы управления валидацией в интерфейсе вставки не были назначены группе валидации. Это работает нормально при условии, что интерфейс вставки является единственным комплектом контролей валидации на странице. Однако если на странице есть другие элементы управления проверкой (например, элементы управления проверки в интерфейсе редактирования сетки), элементы управления проверкой в интерфейсе вставки и свойства кнопки "Добавить" ValidationGroup
должны быть назначены таким же значением, чтобы связать эти элементы управления с определенной группой проверки. Дополнительные сведения о разделении элементов управления и кнопок на странице в группы проверки можно найти в статье Dissecting the Validation Controls in ASP.NET 2.0.
Шаг 5. Вставка новой записи в таблицуProducts
При использовании встроенных функций редактирования GridView, GridView автоматически обрабатывает всю необходимую работу для выполнения обновления. В частности, когда нажимается кнопка "Обновить", она копирует значения, введенные из интерфейса редактирования, в параметры коллекции UpdateParameters
ObjectDataSource и запускает обновление, вызывая метод Update()
ObjectDataSource. Так как GridView не предоставляет такие встроенные функции для вставки, необходимо реализовать код, который вызывает метод Insert()
в ObjectDataSource и копирует значения из интерфейса вставки в коллекцию InsertParameters
в ObjectDataSource.
Эта логика вставки должна выполняться после нажатия кнопки "Добавить". Как обсуждалось в руководстве по добавлению и реагированию на кнопки в GridView, при каждом клике на кнопку, LinkButton или ImageButton в GridView, событие RowCommand
GridView запускается при обратной отправке. Это событие срабатывает как в случае явного добавления кнопок Button, LinkButton или ImageButton, например, кнопки "Добавить" в нижнем колонтитуле, так и в случае их автоматического добавления компонентом GridView (например, LinkButton в верхней части каждого столбца при активированном параметре сортировки или LinkButton в интерфейсе перехода по страницам при активированном параметре пагинации).
Таким образом, чтобы ответить пользователю, нажав кнопку "Добавить", необходимо создать обработчик событий для события GridView RowCommand
. Так как это событие запускается при нажатии любой кнопки, LinkButton или ImageButton в GridView, важно продолжать логику вставки только в том случае, если CommandName
свойство, переданное в обработчик событий, сопоставляется со CommandName
значением кнопки "Добавить" (Insert). Кроме того, мы также должны продолжать работу, только если контрольные элементы проверки сообщат о действительных данных. Для этого создайте обработчик событий для RowCommand
события со следующим кодом:
protected void Products_RowCommand(object sender, GridViewCommandEventArgs e)
{
// Insert data if the CommandName == "Insert"
// and the validation controls indicate valid data...
if (e.CommandName == "Insert" && Page.IsValid)
{
// TODO: Insert new record...
}
}
Замечание
Возможно, вам интересно, почему обработчик событий трудится проверять свойство Page.IsValid
. Ведь обратная передача не будет отключена, если в интерфейс вставки предоставлены недопустимые данные? Это предположение правильно, если пользователь не отключил JavaScript или принял меры, чтобы обойти логику проверки на стороне клиента. Короче говоря, никогда не следует полагаться строго на проверку на стороне клиента; Перед работой с данными всегда следует выполнять проверку на стороне сервера.
На шаге 1 мы создали ProductsDataSource
ObjectDataSource так, чтобы его метод Insert()
был сопоставлен с методом ProductsBLL
класса AddProduct
. Чтобы вставить новую запись в Products
таблицу, можно просто вызвать метод ObjectDataSource Insert()
:
protected void Products_RowCommand(object sender, GridViewCommandEventArgs e)
{
// Insert data if the CommandName == "Insert"
// and the validation controls indicate valid data...
if (e.CommandName == "Insert" && Page.IsValid)
{
// Insert new record
ProductsDataSource.Insert();
}
}
Теперь, когда метод Insert()
был вызван, все, что остается, заключается в копировании значений из интерфейса вставки в параметры, переданные методу ProductsBLL
класса AddProduct
. Как мы уже видели в руководстве по изучению событий, связанных с вставкой, обновлением и удалением , это можно сделать с помощью события ObjectDataSource Inserting
.
Inserting
В случае, если необходимо программно ссылаться на элементы управления из строки нижнего колонтитула Products
GridView и назначать их значения в коллекцию e.InputParameters
. Если пользователь пропустит значение, например, оставив ReorderLevel
поле TextBox пустым, нужно указать, что вставленное в базу данных значение должно быть NULL
.
AddProducts
Так как метод принимает типы, допускающие значение NULL для полей базы данных, допускающих значение NULL, просто используйте тип, допускающий значение NULL, и задайте его значение null
в том случае, если входные данные пользователя опущены.
protected void ProductsDataSource_Inserting
(object sender, ObjectDataSourceMethodEventArgs e)
{
// Programmatically reference Web controls in the inserting interface...
TextBox NewProductName =
(TextBox)Products.FooterRow.FindControl("NewProductName");
DropDownList NewCategoryID =
(DropDownList)Products.FooterRow.FindControl("NewCategoryID");
DropDownList NewSupplierID =
(DropDownList)Products.FooterRow.FindControl("NewSupplierID");
TextBox NewQuantityPerUnit =
(TextBox)Products.FooterRow.FindControl("NewQuantityPerUnit");
TextBox NewUnitPrice =
(TextBox)Products.FooterRow.FindControl("NewUnitPrice");
TextBox NewUnitsInStock =
(TextBox)Products.FooterRow.FindControl("NewUnitsInStock");
TextBox NewUnitsOnOrder =
(TextBox)Products.FooterRow.FindControl("NewUnitsOnOrder");
TextBox NewReorderLevel =
(TextBox)Products.FooterRow.FindControl("NewReorderLevel");
CheckBox NewDiscontinued =
(CheckBox)Products.FooterRow.FindControl("NewDiscontinued");
// Set the ObjectDataSource's InsertParameters values...
e.InputParameters["productName"] = NewProductName.Text;
e.InputParameters["supplierID"] =
Convert.ToInt32(NewSupplierID.SelectedValue);
e.InputParameters["categoryID"] =
Convert.ToInt32(NewCategoryID.SelectedValue);
string quantityPerUnit = null;
if (!string.IsNullOrEmpty(NewQuantityPerUnit.Text))
quantityPerUnit = NewQuantityPerUnit.Text;
e.InputParameters["quantityPerUnit"] = quantityPerUnit;
decimal? unitPrice = null;
if (!string.IsNullOrEmpty(NewUnitPrice.Text))
unitPrice = Convert.ToDecimal(NewUnitPrice.Text);
e.InputParameters["unitPrice"] = unitPrice;
short? unitsInStock = null;
if (!string.IsNullOrEmpty(NewUnitsInStock.Text))
unitsInStock = Convert.ToInt16(NewUnitsInStock.Text);
e.InputParameters["unitsInStock"] = unitsInStock;
short? unitsOnOrder = null;
if (!string.IsNullOrEmpty(NewUnitsOnOrder.Text))
unitsOnOrder = Convert.ToInt16(NewUnitsOnOrder.Text);
e.InputParameters["unitsOnOrder"] = unitsOnOrder;
short? reorderLevel = null;
if (!string.IsNullOrEmpty(NewReorderLevel.Text))
reorderLevel = Convert.ToInt16(NewReorderLevel.Text);
e.InputParameters["reorderLevel"] = reorderLevel;
e.InputParameters["discontinued"] = NewDiscontinued.Checked;
}
После завершения обработчика событий Inserting
, новые записи можно добавлять в таблицу базы данных Products
через нижнюю строку GridView. Идите вперед и попробуйте добавить несколько новых продуктов.
Повышение и настройка операции добавления
В настоящее время нажатие кнопки "Добавить" добавляет новую запись в таблицу базы данных, но не предоставляет никаких визуальных отзывов о том, что запись успешно добавлена. В идеале элемент управления веб-ярлыком или диалоговое окно предупреждения на стороне клиента может сообщить пользователю, что их вставка завершилась успешно. Я оставлю это как упражнение для читателя.
GridView, используемый в этом руководстве, не применяет порядок сортировки к перечисленным продуктам и не позволяет конечным пользователям сортировать данные. Следовательно, записи упорядочены в том порядке, в котором они находятся в базе данных по полю первичного ключа. Каждая новая запись имеет ProductID
значение, которое больше, чем у предыдущей, поэтому каждый раз, когда добавляется новый продукт, запись помещается в конец сетки. Поэтому вы можете автоматически отправить пользователя на последнюю страницу GridView после добавления новой записи. Это можно сделать, добавив следующую строку кода после вызова ProductsDataSource.Insert()
в RowCommand
обработчик событий, чтобы указать, что пользователь должен быть отправлен на последнюю страницу после привязки данных к GridView:
// Indicate that the user needs to be sent to the last page
SendUserToLastPage = true;
SendUserToLastPage
— это логическая переменная уровня страницы, которой изначально присваивается значение false
. В обработчике событий GridView DataBound
, если SendUserToLastPage
— false, свойство PageIndex
обновляется для отправки пользователя на последнюю страницу.
protected void Products_DataBound(object sender, EventArgs e)
{
// Send user to last page of data, if needed
if (SendUserToLastPage)
Products.PageIndex = Products.PageCount - 1;
}
Причина, по которой свойство PageIndex
задано в обработчике событий DataBound
(в отличие от обработчика событий RowCommand
), заключается в том, что при срабатывании обработчика событий RowCommand
мы еще не добавили новую запись в таблицу базы данных Products
. Поэтому в обработчике RowCommand
событий последний индекс страницы (PageCount - 1
) представляет последний индекс страницы перед добавлением нового продукта. Для большинства добавляемых продуктов последний индекс страницы совпадает после добавления нового продукта. Но если добавленный продукт приводит к новому индексу последней страницы, и мы неправильно обновим PageIndex
в обработчике события RowCommand
, то перейдем на предпоследнюю страницу (индекс страницы до добавления нового продукта) вместо нового индекса последней страницы.
DataBound
Поскольку обработчик событий срабатывает после добавления нового продукта и привязки данных обратно к сетке, задавая свойство PageIndex
, мы знаем, что получаем правильный индекс последней страницы.
Наконец, GridView, используемый в этом руководстве, довольно широк из-за количества полей, которые необходимо собрать для добавления нового продукта. Из-за этой ширины может быть предпочтителен вертикальный макет DetailsView. Общая ширина GridView может быть сокращена путем сбора меньшего количества входных данных. Возможно, нам не нужно собирать поля UnitsOnOrder
, UnitsInStock
и ReorderLevel
при добавлении нового продукта, в этом случае эти поля можно удалить из GridView.
Чтобы настроить собранные данные, можно использовать один из двух подходов:
- Продолжайте использовать
AddProduct
метод, который ожидает значения дляUnitsOnOrder
UnitsInStock
полей иReorderLevel
полей. В обработчикеInserting
событий укажите жестко закодированные значения по умолчанию для этих входных данных, которые были удалены из интерфейса вставки. - Создайте новую перегрузку метода
AddProduct
в классеProductsBLL
, которая не принимает входные данные для полейUnitsOnOrder
,UnitsInStock
иReorderLevel
. Затем на странице ASP.NET настройте ObjectDataSource для использования этой новой перегрузки.
Любой из вариантов также будет работать одинаково. В предыдущих руководствах мы использовали последний вариант, создавая несколько перегрузок метода ProductsBLL
класса UpdateProduct
.
Сводка
GridView не имеет встроенных возможностей вставки, как в DetailsView и FormView, но интерфейс вставки можно добавить в строку футера, приложив небольшие усилия. Чтобы отобразить строку нижнего колонтитула в GridView, просто задайте для его свойства значение ShowFooter
true
. Содержимое строки нижнего колонтитула можно настроить для каждого поля, преобразовав поле в TemplateField и добавив интерфейс вставки в FooterTemplate
. Как мы видели в этом руководстве, FooterTemplate
может содержать кнопки, текстовые поля, выпадающие списки, флажки, элементы управления источниками данных для заполнения веб-элементов управления на основе данных (таких как выпадающие списки), и элементы управления проверки. Наряду с элементами управления для сбора входных данных пользователя требуется кнопка "Добавить", LinkButton или ImageButton.
При нажатии кнопки "Добавить" вызывается метод ObjectDataSource Insert()
для запуска рабочего процесса вставки. ObjectDataSource вызовет настроенный метод вставки (метод класса ProductsBLL
AddProduct
в этом руководстве). Необходимо скопировать значения из интерфейса вставки GridView в коллекцию ObjectDataSource InsertParameters
перед вызовом метода вставки. Это можно сделать программным способом за счёт использования веб-элементов управления интерфейса вставки в обработчике событий ObjectDataSource Inserting
.
В этом руководстве мы рассмотрим методы улучшения внешнего вида GridView. В следующем наборе руководств показано, как работать с двоичными данными, такими как изображения, PDF-файлы, документы Word и т. д. и веб-элементы управления данными.
Счастливое программирование!
Сведения о авторе
Скотт Митчелл, автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга — Sams Teach Yourself ASP.NET 2.0 за 24 часа. С ним можно связаться по адресу mitchell@4GuysFromRolla.com.
Особое спасибо кому
Эта серия учебников была проверена многими полезными рецензентами. Ведущий редактор этого учебника была Бернадетт Ли. Хотите просмотреть мои предстоящие статьи MSDN? Если да, напишите мне на mitchell@4GuysFromRolla.com.