Поделиться через


Вставка новой записи из нижнего колонтитула GridView (VB)

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

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

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

Введение

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

При добавлении возможностей вставки в GridView мы отвечаем за принятие решения о том, как будут добавляться новые записи, создавать интерфейс вставки и писать код для вставки новой записи. В этом руководстве мы рассмотрим добавление интерфейса вставки в строку нижнего колонтитула GridView (см. рис. 1). Ячейка нижнего колонтитула для каждого столбца содержит соответствующий элемент пользовательского интерфейса сбора данных (TextBox для названия продукта, DropDownList для поставщика и т. д.). Нам также нужен столбец для кнопки Добавить, который при нажатии будет вызывать обратную передачу и вставлять новую запись в таблицу Products , используя значения, указанные в строке нижнего колонтитула.

Строка нижнего колонтитула предоставляет интерфейс для добавления новых продуктов

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

Шаг 1. Отображение сведений о продукте в GridView

Прежде чем приступить к созданию интерфейса вставки в нижнем колонтитуле GridView, давайте сначала сосредоточимся на добавлении GridView на страницу со списком продуктов в базе данных. Начните с открытия InsertThroughFooter.aspx страницы в папке EnhancedGridView и перетащите GridView из панели элементов на Designer, задав свойству GridView ID значение Products. Затем используйте смарт-тег GridView, чтобы привязать его к новому объекту ObjectDataSource с именем ProductsDataSource.

Создание объекта ObjectDataSource с именем ProductsDataSource

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

Настройте ObjectDataSource для использования ProductsBLL метода класса для GetProducts() получения сведений о продукте. В этом руководстве мы сосредоточимся исключительно на добавлении возможностей вставки и не будем беспокоиться о редактировании и удалении. Поэтому убедитесь, что для раскрывающегося списка на вкладке ВСТАВКА задано значение AddProduct() , а для раскрывающихся списков на вкладках UPDATE и DELETE задано значение (Нет).

Сопоставление метода AddProduct с методом Insert() объекта ObjectDataSource

Рис. 3. Сопоставление AddProduct метода с методом ObjectDataSource Insert() (щелкните для просмотра полноразмерного изображения)

Задайте для Drop-Down Списки вкладок UPDATE и DELETE значение (Нет)

Рис. 4. Задайте для Drop-Down Списки вкладок UPDATE и DELETE значение (Нет) (щелкните для просмотра полноразмерного изображения)

После завершения работы мастера настройки источника данных 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>

Все поля данных о продукте отображаются в выстраивном представлении GridView

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

Вместе со строками заголовков и данных GridView включает строку нижнего колонтитула. Строки колонтитулов отображаются в зависимости от значений свойств GridView ShowHeader и ShowFooter . Чтобы отобразить строку нижнего колонтитула, просто присвойте свойству ShowFooter значение True. Как показано на рисунке 6, для свойства ShowFooter добавляется True строка нижнего колонтитула в сетку.

Чтобы отобразить строку нижнего колонтитула, установите для showFooter значение True.

Рис. 6. Чтобы отобразить строку нижнего колонтитула, установите значение ShowFooterTrue (Щелкните для просмотра полноразмерного изображения)

Обратите внимание, что строка нижнего колонтитула имеет темно-красный цвет фона. Это связано с темой 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. Строка пустого нижнего колонтитула отображается над элементами управления интерфейсом подкачки (щелкните для просмотра полноразмерного изображения)

В руководстве По использованию templateFields в элементе управления GridView мы узнали, как настроить отображение определенного столбца GridView с помощью TemplateFields (в отличие от BoundFields или CheckBoxFields); В разделе Настройка интерфейса изменения данных мы рассмотрели использование TemplateFields для настройки интерфейса редактирования в GridView. Помните, что TemplateField состоит из нескольких шаблонов, которые определяют сочетание разметки, веб-элементов управления и синтаксиса привязки данных, используемого для определенных типов строк. , ItemTemplateнапример, задает шаблон, используемый для строк, доступных только для чтения, а EditItemTemplate определяет шаблон для редактируемой строки.

Наряду с ItemTemplate и EditItemTemplatetemplateField также содержит FooterTemplate объект , указывающий содержимое строки нижнего колонтитула. Таким образом, мы можем добавить веб-элементы управления, необходимые для каждого интерфейса вставки полей, в FooterTemplate. Для начала преобразуйте все поля в GridView в TemplateFields. Это можно сделать, щелкнув ссылку Изменить столбцы в смарт-теге GridView, выбрав каждое поле в левом нижнем углу и щелкнув ссылку Преобразовать это поле в TemplateField.

Преобразование каждого поля в templateField

Рис. 8. Преобразование каждого поля в TemplateField

Если щелкнуть Преобразовать это поле в TemplateField, текущий тип поля преобразуется в эквивалент TemplateField. Например, каждый BoundField заменяется шаблоном TemplateField с ItemTemplate элементом , который содержит метку, отображающую соответствующее поле данных, и EditItemTemplate , отображающую поле данных в Элементе TextBox. BoundField ProductName был преобразован в следующую разметку 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>

Аналогичным образом CheckBoxField был преобразован в TemplateField, Discontinued в котором ItemTemplate и EditItemTemplate содержат веб-элемент управления CheckBox (с отключенным элементом ItemTemplate CheckBox). BoundField, доступный только для ProductID чтения, был преобразован в TemplateField с элементом управления Label в и ItemTemplateEditItemTemplate. Короче говоря, преобразование существующего поля 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 и перетащите соответствующий элемент управления из панели элементов в Designer.

Добавление соответствующего интерфейса вставки в нижний колонтитул каждого поля

Рис. 9. Добавление соответствующего интерфейса вставки в каждое поле FooterTemplate (щелкните для просмотра полноразмерного изображения)

Следующий маркированный список перечисляет поля GridView, указывая добавляемый интерфейс вставки:

  • ProductID Ни один.
  • ProductName Добавьте элемент TextBox и задайте для нее ID значение NewProductName. Добавьте также элемент управления RequiredFieldValidator, чтобы убедиться, что пользователь вводит значение для имени нового продукта.
  • SupplierID Ни один.
  • CategoryID Ни один.
  • QuantityPerUnit добавьте элемент TextBox, задав для нее ID значение NewQuantityPerUnit.
  • UnitPrice добавьте элемент TextBox с именем NewUnitPrice и CompareValidator, который гарантирует, что введенное значение является денежным значением, превышающим или равным нулю.
  • UnitsInStock используйте элемент TextBox, для которого ID задано значение NewUnitsInStock. Включите CompareValidator, который гарантирует, что введенное значение является целочисленным значением, превышающим или равным нулю.
  • UnitsOnOrder используйте элемент TextBox, для которого ID задано значение NewUnitsOnOrder. Включите CompareValidator, который гарантирует, что введенное значение является целочисленным значением, превышающим или равным нулю.
  • ReorderLevel используйте элемент TextBox, для которого ID задано значение NewReorderLevel. Включите CompareValidator, который гарантирует, что введенное значение является целочисленным значением, превышающим или равным нулю.
  • Discontinued добавьте элемент CheckBox, задав для нее 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 для свойства s Wrap значение false для каждого элемента FooterTemplate управления, использующее элемент управления проверки. Наконец, добавьте элемент управления ValidationSummary под GridView и задайте для его ShowMessageBox свойства значение True , а для свойства ShowSummary — значение False.

При добавлении нового продукта необходимо предоставить CategoryID и SupplierID. Эти сведения записываются с помощью DropDownLists в ячейках нижнего 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 значения в виде валюты, выровнять поля , UnitsOnOrderи ReorderLevel по правому краю UnitsInStockи обновить 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 показано, как вставить новую запись с помощью данных из нижнего колонтитула.

Нижний колонтитул GridView предоставляет интерфейс для добавления новой записи

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

Шаг 4. Включение кнопки "Добавить" в интерфейс вставки

Нам нужно включить кнопку Добавить где-то в интерфейсе вставки, так как в интерфейсе вставки строки нижнего колонтитула в настоящее время отсутствуют средства, позволяющие пользователю указать, что он завершил ввод сведений о новом продукте. Его можно поместить в один из существующих FooterTemplate объектов или добавить новый столбец в сетку для этой цели. Для работы с этим руководством поместим кнопку Добавить в ProductID templateField s FooterTemplate.

В Designer щелкните ссылку Изменить шаблоны в смарт-теге GridView и выберите ProductID поля FooterTemplate из раскрывающегося списка. Добавьте веб-элемент управления Button (или LinkButton или ImageButton, если вы предпочитаете) в шаблон, задав для его идентификатора AddProductзначение , а для свойства CommandName — значение Добавить, Text как показано на рисунке 11.

Поместите кнопку

Рис. 11. Поместите кнопку "Добавить" в ProductID templateField (FooterTemplateщелкните для просмотра полноразмерного изображения)

После добавления кнопки Добавить проверьте страницу в браузере. Обратите внимание, что при нажатии кнопки Добавить с недопустимыми данными в интерфейсе вставки обратная передача завершается коротко, а элемент управления ValidationSummary указывает на недопустимые данные (см. рис. 12). При вводе соответствующих данных нажатие кнопки Добавить приводит к обратной отправке. Однако запись не добавляется в базу данных. Нам потребуется написать немного кода, чтобы фактически выполнить вставку.

Обратная передача кнопки

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

Примечание

Элементы управления проверки в интерфейсе вставки не были назначены группе проверки. Это работает нормально, если интерфейс вставки является единственным набором элементов управления проверки на странице. Однако если на странице есть другие элементы управления проверки (например, элементы управления проверки в интерфейсе редактирования сетки), то элементам управления проверки в интерфейсе вставки и свойствах кнопки ValidationGroup Добавить следует присвоить то же значение, чтобы связать эти элементы управления с определенной группой проверки. Дополнительные сведения о секционации элементов управления проверкой и кнопок на странице на группы проверки см. в ASP.NET 2.0 .

Шаг 5. Вставка новой записи в таблицуProducts

При использовании встроенных функций редактирования GridView GridView автоматически обрабатывает всю работу, необходимую для выполнения обновления. В частности, при нажатии кнопки Обновить он копирует значения, введенные из интерфейса редактирования, в параметры в коллекции ObjectDataSource UpdateParameters и запускает обновление, вызывая метод ObjectDataSource Update() . Так как GridView не предоставляет таких встроенных функций для вставки, необходимо реализовать код, который вызывает метод ObjectDataSource Insert() и копирует значения из интерфейса вставки в коллекцию ObjectDataSource InsertParameters .

Эта логика вставки должна выполняться после нажатия кнопки Добавить. Как описано в руководстве По добавлению кнопок в GridView и реагированию на них , при каждом щелчке элемента Button, LinkButton или ImageButton в GridView событие GridView RowCommand возникает при обратной отправке. Это событие возникает независимо от того, были ли добавлены button, LinkButton или ImageButton явным образом, например кнопка Добавить в строке нижнего колонтитула или автоматически добавлен gridView (например, LinkButtons в верхней части каждого столбца при выборе параметра Включить сортировку или LinkButtons в интерфейсе подкачки при выборе параметра Включить разбиение по страницам).

Поэтому, чтобы ответить на нажатие кнопки Добавить, необходимо создать обработчик событий для события GridView RowCommand . Так как это событие возникает всякий раз при щелчке элемента Button, LinkButton или ImageButton в GridView, крайне важно, чтобы мы переходили к логике вставки, только если CommandName свойство, передаваемое в обработчик событий, сопоставляется со значением CommandName кнопки Добавить ( Вставить ). Кроме того, следует продолжать только в том случае, если элементы управления проверкой сообщают о допустимых данных. Чтобы обеспечить это, создайте обработчик событий для RowCommand события со следующим кодом:

Protected Sub Products_RowCommand(sender As Object, e As GridViewCommandEventArgs) _
    Handles Products.RowCommand
    
    ' Insert data if the CommandName == "Insert" 
    ' and the validation controls indicate valid data...
    If e.CommandName = "Insert" AndAlso Page.IsValid Then
        ' TODO: Insert new record...
    End If
End Sub

Примечание

Возможно, вас интересует, почему обработчик событий беспокоит проверку Page.IsValid свойства. В конце концов, не будет ли обратная передача подавляться, если в интерфейсе вставки предоставлены недопустимые данные? Это предположение верно, если пользователь не отключил JavaScript или не принял меры для обхода логики проверки на стороне клиента. Короче говоря, никогда не следует полагаться исключительно на проверку на стороне клиента; перед работой с данными всегда следует выполнять проверка на стороне сервера.

На шаге ProductsDataSource 1 мы создали ObjectDataSource таким образом, чтобы его Insert() метод сопоставляется с методом ProductsBLL класса s AddProduct . Чтобы вставить новую запись в таблицуProducts, можно просто вызвать метод ObjectDataSource:Insert()

Protected Sub Products_RowCommand(sender As Object, e As GridViewCommandEventArgs) _
    Handles Products.RowCommand
    
    ' Insert data if the CommandName == "Insert" 
    ' and the validation controls indicate valid data...
    If e.CommandName = "Insert" AndAlso Page.IsValid Then
        ' Insert new record
        ProductsDataSource.Insert()
    End If
End Sub

Теперь, когда Insert() метод был вызван, осталось скопировать значения из интерфейса вставки в параметры, передаваемые методу ProductsBLL класса .AddProduct Как мы видели в учебнике Изучение событий, связанных с вставкой, обновлением и удалением , это можно сделать с помощью события ObjectDataSource Inserting . В случае Inserting , если нам нужно программно ссылаться на элементы управления из строки нижнего Products колонтитула GridView и присвоить e.InputParameters их значения коллекции. Если пользователь пропускает значение, например оставляя ReorderLevel TextBox пустым, необходимо указать, что значение, вставленное в базу данных, должно иметь значение NULL. AddProducts Так как метод принимает типы, допускаемые значения NULL, для полей базы данных, допускающих значение NULL, просто используйте тип, допускающий значение NULL, и присвойте ей значение Nothing в случае, если введенные пользователем данные опущены.

Protected Sub ProductsDataSource_Inserting _
    (sender As Object, e As .ObjectDataSourceMethodEventArgs) _
    Handles ProductsDataSource.Inserting
    
    ' Programmatically reference Web controls in the inserting interface...
    Dim NewProductName As TextBox = _
        Products.FooterRow.FindControl("NewProductName")
    Dim NewCategoryID As DropDownList = _
        Products.FooterRow.FindControl("NewCategoryID")
    Dim NewSupplierID As DropDownList = _
        Products.FooterRow.FindControl("NewSupplierID")
    Dim NewQuantityPerUnit As TextBox = _
        Products.FooterRow.FindControl("NewQuantityPerUnit")
    Dim NewUnitPrice As TextBox = _
        Products.FooterRow.FindControl("NewUnitPrice")
    Dim NewUnitsInStock As TextBox = _
        Products.FooterRow.FindControl("NewUnitsInStock")
    Dim NewUnitsOnOrder As TextBox = _
        Products.FooterRow.FindControl("NewUnitsOnOrder")
    Dim NewReorderLevel As TextBox = _
        Products.FooterRow.FindControl("NewReorderLevel")
    Dim NewDiscontinued As 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)
    Dim quantityPerUnit As String = Nothing
    If Not String.IsNullOrEmpty(NewQuantityPerUnit.Text) Then
        quantityPerUnit = NewQuantityPerUnit.Text
    End If
    e.InputParameters("quantityPerUnit") = quantityPerUnit
    Dim unitPrice As Nullable(Of Decimal) = Nothing
    If Not String.IsNullOrEmpty(NewUnitPrice.Text) Then
        unitPrice = Convert.ToDecimal(NewUnitPrice.Text)
    End If
    e.InputParameters("unitPrice") = unitPrice
    Dim unitsInStock As Nullable(Of Short) = Nothing
    If Not String.IsNullOrEmpty(NewUnitsInStock.Text) Then
        unitsInStock = Convert.ToInt16(NewUnitsInStock.Text)
    End If
    e.InputParameters("unitsInStock") = unitsInStock
    Dim unitsOnOrder As Nullable(Of Short) = Nothing
    If Not String.IsNullOrEmpty(NewUnitsOnOrder.Text) Then
        unitsOnOrder = Convert.ToInt16(NewUnitsOnOrder.Text)
    End If
    e.InputParameters("unitsOnOrder") = unitsOnOrder
    Dim reorderLevel As Nullable(Of Short) = Nothing
    If Not String.IsNullOrEmpty(NewReorderLevel.Text) Then
        reorderLevel = Convert.ToInt16(NewReorderLevel.Text)
    End If
    e.InputParameters("reorderLevel") = reorderLevel
    e.InputParameters("discontinued") = NewDiscontinued.Checked
End Sub

После завершения обработчика 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. Если в обработчике SendUserToLastPage событий GridView DataBound имеет значение false, PageIndex свойство обновляется для отправки пользователя на последнюю страницу.

Protected Sub Products_DataBound(sender As Object, e As EventArgs) _
    Handles Products.DataBound
    
    ' Send user to last page of data, if needed
    If SendUserToLastPage Then
        Products.PageIndex = Products.PageCount - 1
    End If
End Sub

Причина, 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 , может содержать button, TextBoxes, DropDownLists, CheckBoxes, элементы управления источником данных для заполнения управляемых данными веб-элементов управления (например, DropDownLists) и элементов управления проверки. Наряду с элементами управления для сбора данных, введенных пользователем, требуется кнопка "Добавить", "LinkButton" или "ImageButton".

При нажатии кнопки Добавить вызывается метод ObjectDataSource для Insert() запуска рабочего процесса вставки. Затем ObjectDataSource вызовет настроенный метод insert ( ProductsBLL метод класса s AddProduct в этом руководстве). Необходимо скопировать значения из интерфейса вставки GridView в коллекцию ObjectDataSource InsertParameters перед вызовом метода insert. Это можно сделать путем программной ссылки на веб-элементы управления интерфейса вставки в обработчике событий ObjectDataSource Inserting .

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

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

Об авторе

Скотт Митчелл( 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.