Inserir um novo registro do rodapé do GridView (C#)
por Scott Mitchell
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 de inserção, atualização e exclusão de dados , os controles Web GridView, DetailsView e FormView 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 oferece apenas 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 escrever 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é de 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 de rodapé.
Figura 1: a linha rodapé fornece uma interface para adicionar novos produtos (clique para exibir a 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, primeiro vamos 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 Products
GridView como ID
. Em seguida, use a marca inteligente GridView para associá-la a um novo ObjectDataSource chamado ProductsDataSource
.
Figura 2: Criar um novo objectDataSource chamado ProductsDataSource
(clique para exibir a imagem em tamanho real)
Configure o ObjectDataSource para usar o ProductsBLL
método da classe s GetProducts()
para recuperar informações do produto. Para este tutorial, vamos nos concentrar estritamente em adicionar recursos de inserção e não se preocupar em editar e excluir. 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).
Figura 3: Mapear o AddProduct
método para o método ObjectDataSource (Insert()
clique para exibir a imagem em tamanho real)
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>
Figura 5: Todos os campos de dados do produto são exibidos em um Paged GridView (clique para exibir a imagem em tamanho real)
Etapa 2: adicionando uma linha de rodapé
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
gridViewShowHeader
. Para mostrar a linha de 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.
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 da tela de fundo vermelha escura. Isso ocorre devido ao Tema DataWebControls que criamos e aplicamos a todas as páginas 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 em 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 um atualizador.
Depois de definir a ShowFooter
propriedade true
como , 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.
Figura 7: a linha de rodapé vazia é exibida acima dos controles da interface de paginação (clique para exibir a imagem em tamanho real)
Etapa 3: Personalizando a linha do rodapé
De volta ao tutorial Usando TemplateFields no Controle GridView , vimos como personalizar muito a exibição de uma determinada coluna GridView usando TemplateFields (em vez de BoundFields ou CheckBoxFields); em Personalizando 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 Da 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 EditItemTemplate
o , o TemplateField também inclui um FooterTemplate
que especifica o conteúdo da linha de 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.
Figura 8: Converter cada campo em um TemplateField
Clicar no campo Converter este 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 Label que exibe o campo de dados correspondente e um EditItemTemplate
que exibe o campo de dados em um 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 o ItemTemplate
s CheckBox desabilitado). O BoundField somente ProductID
leitura foi convertido em um TemplateField com um controle Label no e EditItemTemplate
no ItemTemplate
. 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 (ProductID
por exemplo); outros variam 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.
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 uma TextBox e defina comoID
NewProductName
. 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 uma TextBox, definindo-aID
NewQuantityPerUnit
como .UnitPrice
adicione um TextBox chamadoNewUnitPrice
e um CompareValidator que garante que o valor inserido seja um valor de moeda maior ou igual a zero.UnitsInStock
use uma TextBox cujoID
está definido comoNewUnitsInStock
. Inclua um CompareValidator que garanta que o valor inserido seja um valor inteiro maior ou igual a zero.UnitsOnOrder
use uma TextBox cujoID
está definido comoNewUnitsOnOrder
. Inclua um CompareValidator que garanta que o valor inserido seja um valor inteiro maior ou igual a zero.ReorderLevel
use uma TextBox cujoID
está definido comoNewReorderLevel
. Inclua um CompareValidator que garanta que o valor inserido seja um valor inteiro maior ou igual a zero.Discontinued
adicione uma CheckBox, definindo-aID
NewDiscontinued
como .CategoryName
adicione um DropDownList e defina comoID
NewCategoryID
. Associe-o a um novo ObjectDataSource chamadoCategoriesDataSource
e configure-o para usar oCategoriesBLL
método da classe sGetCategories()
. Fazer com que os s DropDownListListItem
exibam oCategoryName
campo de dados, usando oCategoryID
campo de dados como seus valores.SupplierName
adicione um DropDownList e defina comoID
NewSupplierID
. Associe-o a um novo ObjectDataSource chamadoSuppliersDataSource
e configure-o para usar oSuppliersBLL
método da classe sGetSuppliers()
. Fazer com que os s DropDownListListItem
exibam oCompanyName
campo de dados, usando oSupplierID
campo de dados como seus valores.
Para cada um dos controles de validação, limpe 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 a quebra automática 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 e SupplierID
o CategoryID
. Essas informações são capturadas por meio de DropDownLists nas células de rodapé dos CategoryName
campos e SupplierName
. Optei por usar esses campos em oposição aos CategoryID
campos e SupplierID
TemplateFields 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
TemplateFields 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 à direita os UnitsInStock
campos , UnitsOnOrder
e ReorderLevel
e atualizar os HeaderText
valores para TemplateFields.
Depois de criar a quantidade de interfaces de inserção nos FooterTemplate
s, remover o SupplierID
, e CategoryID
TemplateFields e melhorar a estética da grade por meio da formatação e do alinhamento de 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 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é.
Figura 10: o rodapé GridView fornece uma interface para adicionar um novo registro (clique para exibir a 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 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
.
Na Designer, clique no link Editar Modelos na marca inteligente GridView e escolha o ProductID
campo s FooterTemplate
na lista suspensa. Adicione um controle Web Button (ou um LinkButton ou ImageButton, se preferir) ao modelo, definindo sua ID AddProduct
como , como CommandName
Insert e sua Text
propriedade como Adicionar, conforme mostrado na Figura 11.
Figura 11: Colocar o botão Adicionar no ProductID
campo modelo (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.
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 receber o mesmo valor para associar esses controles a um grupo de validação específico. Consulte Dissecar 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 naProducts
tabela
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 for clicado. Conforme discutido no tutorial Adicionando e respondendo a botões em um GridView , sempre que um Button, 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 foi adicionado automaticamente pelo GridView (como o LinkButtons na parte superior de cada coluna quando Habilitar Classificação está selecionado ou o LinkButtons na interface de paginação quando Habilitar Paginação está selecionado).
Portanto, para responder ao usuário clicando no botão Adicionar, precisamos criar um manipulador de eventos para o evento GridView s 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 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...
}
}
Observação
Talvez você esteja se perguntando por que o manipulador de eventos incomoda ao 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: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();
}
}
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.AddProduct
Como vimos 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, precisaremos 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 null
no caso em que a entrada do usuário for omitida.
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;
}
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.
Aprimorando e personalizando a operação de adição
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 Da 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 para 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 é inicialmente atribuída a 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 void Products_DataBound(object sender, EventArgs e)
{
// Send user to last page of data, if needed
if (SendUserToLastPage)
Products.PageIndex = Products.PageCount - 1;
}
O motivo pelo qual a PageIndex
propriedade é definida no DataBound
manipulador de eventos (em oposição ao 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 ter sido 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 PageIndex
no RowCommand
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 após a adição do novo produto e a recuperação de dados para a grade, definindo a PageIndex
propriedade lá, sabemos que estamos obtendo o índice correto da última página.
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 preferencial. A largura geral do GridView pode ser reduzida coletando menos entradas. Talvez não seja necessário coletar os UnitsOnOrder
campos , UnitsInStock
e 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 osUnitsOnOrder
campos ,UnitsInStock
eReorderLevel
.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 naProductsBLL
classe que não aceita entradas para osUnitsOnOrder
campos ,UnitsInStock
eReorderLevel
. 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.