Compartilhar via


Inserir um novo registro do rodapé do GridView (VB)

por Scott Mitchell

Baixar PDF

Embora o controle GridView não forneça suporte interno para inserir um novo registro de dados, este tutorial mostra como aumentar o GridView para incluir uma interface de inserção.

Introdução

Conforme discutido no tutorial Uma Visão Geral da Inserção, Atualização e Exclusão de Dados , os controles GridView, DetailsView e FormView Web incluem recursos internos de modificação de dados. Quando usados com controles declarativos de fonte de dados, esses três controles da Web podem ser configurados de forma rápida e fácil para modificar dados – e em cenários sem a necessidade de escrever uma única linha de código. Infelizmente, somente os controles DetailsView e FormView fornecem recursos internos de inserção, edição e exclusão. O GridView só oferece suporte para edição e exclusão. No entanto, com um pouco de graxa de cotovelo, podemos aumentar o GridView para incluir uma interface de inserção.

Ao adicionar recursos de inserção ao GridView, somos responsáveis por decidir como novos registros serão adicionados, criar a interface de inserção e gravar o código para inserir o novo registro. Neste tutorial, veremos como adicionar a interface de inserção à linha de rodapé do GridView (consulte a Figura 1). A célula de rodapé para cada coluna inclui o elemento de interface do usuário de coleta de dados apropriado (um TextBox para o nome do produto, um DropDownList para o fornecedor e assim por diante). Também precisamos de uma coluna para um botão Adicionar que, quando clicado, causará um postback e inserirá um novo registro na Products tabela usando os valores fornecidos na linha do rodapé.

A linha footer fornece uma interface para adicionar novos produtos

Figura 1: a linha rodapé fornece uma interface para adicionar novos produtos (clique para exibir imagem em tamanho real)

Etapa 1: Exibindo informações do produto em um GridView

Antes de nos preocuparmos com a criação da interface de inserção no rodapé do GridView, vamos primeiro nos concentrar em adicionar um GridView à página que lista os produtos no banco de dados. Comece abrindo a InsertThroughFooter.aspx página na EnhancedGridView pasta e arraste um GridView da Caixa de Ferramentas para o Designer, definindo a propriedade GridView ID como Products. Em seguida, use a marca inteligente GridView para associá-la a um novo ObjectDataSource chamado ProductsDataSource.

Criar um novo objetoDataSource chamado ProductsDataSource

Figura 2: Criar um novo objetoDataSource nomeado ProductsDataSource (clique para exibir a imagem em tamanho real)

Configure o ObjectDataSource para usar o ProductsBLL método da classe s para recuperar informações do GetProducts() produto. Para este tutorial, vamos nos concentrar estritamente em adicionar recursos de inserção e não nos preocupar com edição e exclusão. Portanto, verifique se a lista suspensa na guia INSERT está definida AddProduct() como e se as listas suspensas nas guias UPDATE e DELETE estão definidas como (Nenhum) .

Mapear o método AddProduct para o método Insert() do ObjectDataSource

Figura 3: mapear o AddProduct método para o método ObjectDataSource (Insert()clique para exibir a imagem em tamanho real)

Defina as guias UPDATE e DELETE Drop-Down Listas como (Nenhum)

Figura 4: definir as guias UPDATE e DELETE Drop-Down Listas como (Nenhum) (Clique para exibir a imagem em tamanho real)

Depois de concluir o assistente Configurar Fonte de Dados do ObjectDataSource, o Visual Studio adicionará automaticamente campos ao GridView para cada um dos campos de dados correspondentes. Por enquanto, deixe todos os campos adicionados pelo Visual Studio. Posteriormente neste tutorial, voltaremos e removeremos alguns dos campos cujos valores não precisam ser especificados ao adicionar um novo registro.

Como há cerca de 80 produtos no banco de dados, um usuário terá que rolar todo o caminho até a parte inferior da página da Web para adicionar um novo registro. Portanto, vamos habilitar a paginação para tornar a interface de inserção mais visível e acessível. Para ativar a paginação, basta marcar a caixa de seleção Habilitar Paginação da marca inteligente GridView.

Neste ponto, a marcação declarativa de GridView e ObjectDataSource deve ser semelhante à seguinte:

<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>

Todos os campos de dados do produto são exibidos em um Paged GridView

Figura 5: Todos os campos de dados do produto são exibidos em um Paged GridView (Clique para exibir a imagem em tamanho real)

Juntamente com seu cabeçalho e linhas de dados, o GridView inclui uma linha de rodapé. As linhas de cabeçalho e rodapé são exibidas dependendo dos valores das propriedades e ShowFooter do ShowHeader GridView. Para mostrar a linha do rodapé, basta definir a ShowFooter propriedade como True. Como ilustra a Figura 6, definir a ShowFooter propriedade para True adicionar uma linha de rodapé à grade.

Para exibir a linha do rodapé, defina ShowFooter como True

Figura 6: para exibir a linha do rodapé, defina ShowFooter como True (Clique para exibir a imagem em tamanho real)

Observe que a linha do rodapé tem uma cor de plano de fundo vermelha escura. Isso ocorre devido ao Tema DataWebControls que criamos e aplicamos a todas as páginas novamente no tutorial Exibindo dados com o ObjectDataSource . Especificamente, o GridView.skin arquivo configura a FooterStyle propriedade de modo que é usa a FooterStyle classe CSS. A FooterStyle classe é definida no Styles.css da seguinte maneira:

.FooterStyle
{
    background-color: #a33;
    color: White;
    text-align: right;
}

Observação

Exploramos o uso da linha de rodapé do GridView em tutoriais anteriores. Se necessário, consulte o tutorial Exibindo informações de resumo no Rodapé do GridView para obter uma atualização.

Depois de definir a ShowFooter propriedade como True, reserve um momento para exibir a saída em um navegador. Atualmente, a linha do rodapé não contém nenhum texto ou controles da Web. Na Etapa 3, modificaremos o rodapé de cada campo GridView para que ele inclua a interface de inserção apropriada.

A linha de rodapé vazia é exibida acima dos controles de interface de paginação

Figura 7: a linha de rodapé vazia é exibida acima dos controles da interface de paginação (clique para exibir a imagem em tamanho real)

De volta ao tutorial Usando TemplateFields no GridView Control , vimos como personalizar muito a exibição de uma determinada coluna GridView usando TemplateFields (em vez de BoundFields ou CheckBoxFields); em Personalizar a Interface de Modificação de Dados que examinamos usando TemplateFields para personalizar a interface de edição em um GridView. Lembre-se de que um TemplateField é composto por vários modelos que definem a combinação de marcação, controles Web e sintaxe de vinculação de dados usada para determinados tipos de linhas. O ItemTemplate, por exemplo, especifica o modelo usado para linhas somente leitura, enquanto o EditItemTemplate define o modelo para a linha editável.

Junto com o ItemTemplate e EditItemTemplateo , o TemplateField também inclui um FooterTemplate que especifica o conteúdo da linha do rodapé. Portanto, podemos adicionar os controles da Web necessários para cada interface de inserção de campo no FooterTemplate. Para iniciar, converta todos os campos no GridView em TemplateFields. Isso pode ser feito clicando no link Editar Colunas na marca inteligente GridView, selecionando cada campo no canto inferior esquerdo e clicando no link Converter este campo em um TemplateField.

Converter cada campo em um TemplateField

Figura 8: Converter cada campo em um TemplateField

Clicar no campo Converter esse campo em um TemplateField transforma o tipo de campo atual em um TemplateField equivalente. Por exemplo, cada BoundField é substituído por um TemplateField por um ItemTemplate que contém um Rótulo que exibe o campo de dados correspondente e um EditItemTemplate que exibe o campo de dados em uma TextBox. O ProductName BoundField foi convertido na seguinte marcação 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>

Da mesma forma, o Discontinued CheckBoxField foi convertido em um TemplateField cujo ItemTemplate e EditItemTemplate contêm um controle Web CheckBox (com a Caixa de Seleção ItemTemplate desabilitada). O BoundField somente ProductID leitura foi convertido em um TemplateField com um controle Label no ItemTemplate e EditItemTemplateno . Em suma, converter um campo GridView existente em um TemplateField é uma maneira rápida e fácil de alternar para o TemplateField mais personalizável sem perder nenhuma das funcionalidades existentes do campo.

Como o GridView com o qual estamos trabalhando não dá suporte à edição, fique à vontade para remover o EditItemTemplate de cada TemplateField, deixando apenas o ItemTemplate. Depois de fazer isso, a marcação declarativa do GridView deve ser semelhante à seguinte:

<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>

Agora que cada campo GridView foi convertido em um TemplateField, podemos inserir a interface de inserção apropriada em cada campo s FooterTemplate. Alguns dos campos não terão uma interface de inserção (ProductIDpor exemplo); outros variarão nos controles da Web usados para coletar as informações do novo produto.

Para criar a interface de edição, escolha o link Editar Modelos na marca inteligente GridView. Em seguida, na lista suspensa, selecione os campos apropriados FooterTemplate e arraste o controle apropriado da Caixa de Ferramentas para o Designer.

Adicionar a interface de inserção apropriada a cada campo footerTemplate

Figura 9: adicionar a interface de inserção apropriada a cada campo s FooterTemplate (clique para exibir a imagem em tamanho real)

A seguinte lista com marcadores enumera os campos GridView, especificando a interface de inserção a ser adicionada:

  • ProductID Nenhum.
  • ProductName adicione um TextBox e defina como IDNewProductName. Adicione um controle RequiredFieldValidator também para garantir que o usuário insira um valor para o nome do novo produto.
  • SupplierID Nenhum.
  • CategoryID Nenhum.
  • QuantityPerUnit adicione um TextBox, definindo-o ID como NewQuantityPerUnit.
  • UnitPrice adicione um TextBox chamado NewUnitPrice e um CompareValidator que garante que o valor inserido seja um valor de moeda maior ou igual a zero.
  • UnitsInStock use um TextBox cujo ID está definido como NewUnitsInStock. Inclua um CompareValidator que garante que o valor inserido seja um valor inteiro maior ou igual a zero.
  • UnitsOnOrder use um TextBox cujo ID está definido como NewUnitsOnOrder. Inclua um CompareValidator que garante que o valor inserido seja um valor inteiro maior ou igual a zero.
  • ReorderLevel use um TextBox cujo ID está definido como NewReorderLevel. Inclua um CompareValidator que garante que o valor inserido seja um valor inteiro maior ou igual a zero.
  • Discontinued adicione uma CheckBox, definindo-a ID como NewDiscontinued.
  • CategoryName adicione um DropDownList e defina como IDNewCategoryID. Associe-o a um novo ObjectDataSource chamado CategoriesDataSource e configure-o para usar o CategoriesBLL método da classe s GetCategories() . Fazer com que os dropDownLists ListItem exibam o CategoryName campo de dados, usando o CategoryID campo de dados como seus valores.
  • SupplierName adicione um DropDownList e defina como IDNewSupplierID. Associe-o a um novo ObjectDataSource chamado SuppliersDataSource e configure-o para usar o SuppliersBLL método da classe s GetSuppliers() . Fazer com que os dropDownLists ListItem exibam o CompanyName campo de dados, usando o SupplierID campo de dados como seus valores.

Para cada um dos controles de validação, desmarque a ForeColor propriedade para que a FooterStyle cor de primeiro plano branca da classe CSS seja usada no lugar do vermelho padrão. Use também a ErrorMessage propriedade para uma descrição detalhada, mas defina a Text propriedade como um asterisco. Para impedir que o texto do controle de validação cause o encapsulamento da interface de inserção em duas linhas, defina a FooterStyle propriedade s Wrap como false para cada um dos FooterTemplate s que usam um controle de validação. Por fim, adicione um controle ValidationSummary abaixo do GridView e defina sua ShowMessageBox propriedade como True e sua ShowSummary propriedade como False.

Ao adicionar um novo produto, precisamos fornecer o CategoryID e SupplierID. Essas informações são capturadas por meio do DropDownLists nas células de rodapé dos CategoryName campos e SupplierName . Optei por usar esses campos em vez de CategoryID TemplateFields e SupplierID porque nas linhas de dados da grade o usuário provavelmente está mais interessado em ver os nomes de categoria e fornecedor em vez de seus valores de ID. Como os CategoryID valores e SupplierID agora estão sendo capturados nas CategoryName interfaces de inserção do campo e SupplierName , podemos remover os CategoryID Campos de Modelo e SupplierID do GridView.

Da mesma forma, o ProductID não é usado ao adicionar um novo produto, portanto, o ProductID TemplateField também pode ser removido. No entanto, vamos deixar o ProductID campo na grade. Além dos controles TextBoxes, DropDownLists, CheckBoxes e validação que compõem a interface de inserção, também precisaremos de um botão Adicionar que, quando clicado, execute a lógica para adicionar o novo produto ao banco de dados. Na Etapa 4, incluiremos um botão Adicionar na interface de inserção no ProductID TemplateField s FooterTemplate.

Fique à vontade para melhorar a aparência dos vários campos gridView. Por exemplo, talvez você queira formatar os UnitPrice valores como uma moeda, alinhar com o botão direito dos UnitsInStockcampos , UnitsOnOrdere ReorderLevel e atualizar os HeaderText valores de TemplateFields.

Depois de criar a variedade de interfaces de inserção nos FooterTemplate s, remover os SupplierIDCampos de Modelo e CategoryID e melhorar a estética da grade por meio da formatação e do alinhamento dos TemplateFields, a marcação declarativa do GridView deve ser semelhante à seguinte:

<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>

Quando exibida por meio de um navegador, a linha de rodapé do GridView agora inclui a interface de inserção concluída (consulte a Figura 10). Neste ponto, a interface de inserção não inclui um meio para o usuário indicar que ela inseriu os dados do novo produto e deseja inserir um novo registro no banco de dados. Além disso, ainda não abordamos como os dados inseridos no rodapé serão convertidos em um novo registro no Products banco de dados. Na Etapa 4, veremos como incluir um botão Adicionar à interface de inserção e como executar código no postback quando ele for clicado. A etapa 5 mostra como inserir um novo registro usando os dados do rodapé.

O Rodapé gridview fornece uma interface para adicionar um novo registro

Figura 10: o rodapé gridview fornece uma interface para adicionar um novo registro (clique para exibir imagem em tamanho real)

Etapa 4: Incluindo um botão Adicionar na interface de inserção

Precisamos incluir um botão Adicionar em algum lugar na interface de inserção, pois a interface de inserção da linha de rodapé atualmente não tem os meios para o usuário indicar que ele concluiu a inserção das informações do novo produto. Isso pode ser colocado em um dos s existentes FooterTemplate ou podemos adicionar uma nova coluna à grade para essa finalidade. Para este tutorial, vamos colocar o botão Adicionar no ProductID TemplateField s FooterTemplate.

No Designer, clique no link Editar Modelos na marca inteligente GridView e escolha os ProductID campos na FooterTemplate lista suspensa. Adicione um controle Web button (ou um LinkButton ou ImageButton, se preferir) ao modelo, definindo sua ID como AddProduct, sua CommandName como Inserir e sua Text propriedade como Adicionar, conforme mostrado na Figura 11.

Coloque o botão Adicionar no ProductID TemplateField s FooterTemplate

Figura 11: coloque o botão Adicionar no ProductID TemplateField s FooterTemplate (Clique para exibir a imagem em tamanho real)

Depois de incluir o botão Adicionar, teste a página em um navegador. Observe que, ao clicar no botão Adicionar com dados inválidos na interface de inserção, o postback é curto-circuito e o controle ValidationSummary indica os dados inválidos (consulte a Figura 12). Com os dados apropriados inseridos, clicar no botão Adicionar causa um postback. No entanto, nenhum registro é adicionado ao banco de dados. Precisaremos escrever um pouco de código para realmente executar a inserção.

O Postback do Botão Adicionar será curto-circuito se houver dados inválidos na interface de inserção

Figura 12: o Postback do Botão Adicionar será curto-circuito se houver dados inválidos na interface de inserção (clique para exibir a imagem em tamanho real)

Observação

Os controles de validação na interface de inserção não foram atribuídos a um grupo de validação. Isso funciona bem desde que a interface de inserção seja o único conjunto de controles de validação na página. Se, no entanto, houver outros controles de validação na página (como controles de validação na interface de edição da grade), os controles de validação na interface de inserção e as propriedades do ValidationGroup botão Adicionar devem ser atribuídos ao mesmo valor para associar esses controles a um grupo de validação específico. Consulte Dissecando os controles de validação no ASP.NET 2.0 para obter mais informações sobre como particionar os controles e botões de validação em uma página em grupos de validação.

Etapa 5: Inserindo um novo registro naProductstabela

Ao utilizar os recursos de edição internos do GridView, o GridView manipula automaticamente todo o trabalho necessário para executar a atualização. Em particular, quando o botão Atualizar é clicado, ele copia os valores inseridos da interface de edição para os parâmetros na coleção ObjectDataSource e UpdateParameters inicia a atualização invocando o método ObjectDataSource.Update() Como o GridView não fornece essa funcionalidade interna para inserção, devemos implementar o código que chama o método ObjectDataSource e Insert() copia os valores da interface de inserção para a coleção ObjectDataSource InsertParameters .

Essa lógica de inserção deve ser executada depois que o botão Adicionar tiver sido clicado. Conforme discutido no tutorial Adicionando e respondendo a botões em um tutorial do GridView , sempre que um Botão, LinkButton ou ImageButton em um GridView é clicado, o evento GridView é RowCommand acionado no postback. Esse evento aciona se Button, LinkButton ou ImageButton foi adicionado explicitamente, como o botão Adicionar na linha do rodapé ou se ele foi adicionado automaticamente pelo GridView (como o LinkButtons na parte superior de cada coluna quando Habilitar Classificação é selecionado ou o LinkButtons na interface de paginação quando Habilitar Paginação é selecionado).

Portanto, para responder ao usuário clicando no botão Adicionar, precisamos criar um manipulador de eventos para o evento GridView.RowCommand Como esse evento é acionado sempre que qualquer Button, LinkButton ou ImageButton no GridView é clicado, é vital que continuemos apenas com a lógica de inserção se a CommandName propriedade passada para o manipulador de eventos for mapeada para o CommandName valor do botão Adicionar ( Inserir ). Além disso, também devemos continuar somente se os controles de validação relatarem dados válidos. Para acomodar isso, crie um manipulador de eventos para o RowCommand evento com o seguinte código:

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

Observação

Talvez você esteja se perguntando por que o manipulador de eventos se incomoda em verificar a Page.IsValid propriedade. Afinal, o postback não será suprimido se dados inválidos forem fornecidos na interface de inserção? Essa suposição está correta desde que o usuário não tenha desabilitado o JavaScript ou tenha tomado medidas para contornar a lógica de validação do lado do cliente. Em suma, nunca se deve depender estritamente da validação do lado do cliente; um marcar do lado do servidor para validade sempre deve ser executado antes de trabalhar com os dados.

Na Etapa 1, criamos o ProductsDataSource ObjectDataSource de modo que seu Insert() método seja mapeado para o ProductsBLL método da classe s AddProduct . Para inserir o novo registro na Products tabela, podemos simplesmente invocar o método ObjectDataSource s 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

Agora que o Insert() método foi invocado, tudo o que resta é copiar os valores da interface de inserção para os parâmetros passados para o ProductsBLL método da classe s AddProduct . Como vimos novamente no tutorial Examinando os eventos associados à inserção, atualização e exclusão , isso pode ser feito por meio do evento ObjectDataSource Inserting . Inserting Caso precisemos referenciar programaticamente os controles da linha de Products rodapé do GridView e atribuir seus valores à e.InputParameters coleção. Se o usuário omitir um valor como deixar o ReorderLevel TextBox em branco, precisamos especificar que o valor inserido no banco de dados deve ser NULL. Como o AddProducts método aceita tipos anuláveis para os campos de banco de dados anuláveis, basta usar um tipo anulável e definir seu valor como Nothing no caso em que a entrada do usuário é omitida.

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

Com o Inserting manipulador de eventos concluído, novos registros podem ser adicionados à tabela de Products banco de dados por meio da linha de rodapé do GridView. Vá em frente e tente adicionar vários novos produtos.

Aprimoramento e personalização da operação Adicionar

Atualmente, clicar no botão Adicionar adiciona um novo registro à tabela de banco de dados, mas não fornece nenhum tipo de comentário visual que o registro tenha sido adicionado com êxito. O ideal é que um controle Web de rótulo ou uma caixa de alerta do lado do cliente informe ao usuário que sua inserção foi concluída com êxito. Eu deixo isso como um exercício para o leitor.

O GridView usado neste tutorial não aplica nenhuma ordem de classificação aos produtos listados, nem permite que o usuário final classifique os dados. Consequentemente, os registros são ordenados como estão no banco de dados pelo campo de chave primária. Como cada novo registro tem um ProductID valor maior que o último, sempre que um novo produto é adicionado, ele é abordado no final da grade. Portanto, talvez você queira enviar automaticamente o usuário para a última página do GridView depois de adicionar um novo registro. Isso pode ser feito adicionando a seguinte linha de código após a chamada ao ProductsDataSource.Insert() no RowCommand manipulador de eventos para indicar que o usuário precisa ser enviado para a última página depois de associar os dados ao GridView:

' Indicate that the user needs to be sent to the last page
SendUserToLastPage = True

SendUserToLastPage é uma variável booliana no nível da página que recebe inicialmente um valor de False. No manipulador de eventos gridview DataBound , se SendUserToLastPage for false, a PageIndex propriedade será atualizada para enviar o usuário para a última página.

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

O motivo pelo qual a PageIndex propriedade é definida no DataBound manipulador de eventos (em vez do RowCommand manipulador de eventos) é porque quando o RowCommand manipulador de eventos é acionado, ainda não adicionamos o novo registro à tabela de Products banco de dados. Portanto, no RowCommand manipulador de eventos, o último índice de página (PageCount - 1) representa o último índice de página antes de o novo produto ser adicionado. Para a maioria dos produtos que estão sendo adicionados, o índice da última página é o mesmo depois de adicionar o novo produto. Mas quando o produto adicionado resultar em um novo índice de última página, se atualizarmos incorretamente o PageIndexRowCommand no manipulador de eventos, seremos levados para a segunda para a última página (o último índice de página antes de adicionar o novo produto) em vez do novo índice da última página. Como o DataBound manipulador de eventos é acionado depois que o novo produto é adicionado e os dados se recuperam para a grade, definindo a PageIndex propriedade lá, sabemos que estamos obtendo o índice de última página correto.

Por fim, o GridView usado neste tutorial é bastante amplo devido ao número de campos que devem ser coletados para adicionar um novo produto. Devido a essa largura, um layout vertical do DetailsView pode ser preferido. A largura geral do GridView pode ser reduzida coletando menos entradas. Talvez não seja necessário coletar os UnitsOnOrdercampos , UnitsInStocke ReorderLevel ao adicionar um novo produto, nesse caso, esses campos podem ser removidos do GridView.

Para ajustar os dados coletados, podemos usar uma das duas abordagens:

  • Continue a usar o AddProduct método que espera valores para os UnitsOnOrdercampos , UnitsInStocke ReorderLevel . Inserting No manipulador de eventos, forneça valores padrão embutidos em código a serem usados para essas entradas que foram removidas da interface de inserção.
  • Crie uma nova sobrecarga do AddProduct método na ProductsBLL classe que não aceita entradas para os UnitsOnOrdercampos , UnitsInStocke ReorderLevel . Em seguida, na página ASP.NET, configure o ObjectDataSource para usar essa nova sobrecarga.

Qualquer uma das opções funcionará igualmente também. Em tutoriais anteriores, usamos a última opção, criando várias sobrecargas para o ProductsBLL método da classe s UpdateProduct .

Resumo

O GridView não tem os recursos de inserção internos encontrados no DetailsView e no FormView, mas com um pouco de esforço, uma interface de inserção pode ser adicionada à linha de rodapé. Para exibir a linha de rodapé em um GridView, basta definir sua ShowFooter propriedade como True. O conteúdo da linha de rodapé pode ser personalizado para cada campo convertendo o campo em um TemplateField e adicionando a interface de inserção ao FooterTemplate. Como vimos neste tutorial, o FooterTemplate pode conter Botões, TextBoxes, DropDownLists, CheckBoxes, controles de fonte de dados para preencher controles da Web controlados por dados (como DropDownLists) e controles de validação. Juntamente com os controles para coletar a entrada do usuário, um Botão Adicionar, LinkButton ou ImageButton é necessário.

Quando o botão Adicionar é clicado, o método objectDataSource é Insert() invocado para iniciar o fluxo de trabalho de inserção. O ObjectDataSource chamará o método insert configurado (o ProductsBLL método de classe s AddProduct , neste tutorial). Devemos copiar os valores da interface de inserção gridView para a coleção ObjectDataSource antes InsertParameters do método insert ser invocado. Isso pode ser feito referenciando programaticamente os controles da Web da interface de inserção no manipulador de eventos objectDataSource.Inserting

Este tutorial conclui nossas técnicas para aprimorar a aparência do GridView. O próximo conjunto de tutoriais examinará como trabalhar com dados binários, como imagens, PDFs, documentos Word e assim por diante e os controles da Web de dados.

Programação feliz!

Sobre o autor

Scott Mitchell, autor de sete livros do ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Microsoft Web desde 1998. Scott trabalha como consultor independente, treinador e escritor. Seu último livro é Sams Teach Yourself ASP.NET 2.0 em 24 Horas. Ele pode ser contatado em mitchell@4GuysFromRolla.com. ou através de seu blog, que pode ser encontrado em http://ScottOnWriting.NET.

Agradecimentos Especiais

Esta série de tutoriais foi revisada por muitos revisores úteis. A revisora principal deste tutorial foi Berne Leigh. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, deixe-me uma linha em mitchell@4GuysFromRolla.com.