Uma visão geral da inserção, atualização e exclusão de dados (C#)
por Scott Mitchell
Neste tutorial, veremos como mapear os métodos Insert(), Update() e Delete() de um ObjectDataSource para os métodos de classes BLL, bem como configurar os controles GridView, DetailsView e FormView para fornecer recursos de modificação de dados.
Introdução
Nos últimos tutoriais, examinamos como exibir dados em uma página ASP.NET usando os controles GridView, DetailsView e FormView. Esses controles simplesmente funcionam com os dados fornecidos a eles. Normalmente, esses controles acessam dados por meio do uso de um controle de fonte de dados, como o ObjectDataSource. Vimos como o ObjectDataSource atua como um proxy entre a página ASP.NET e os dados subjacentes. Quando um GridView precisa exibir dados, ele invoca o método de Select()
seu ObjectDataSource, que, por sua vez, invoca um método de nossa BLL (Business Logic Layer), que chama um método no TableAdapter da DAL (Data Access Layer) apropriado, que, por sua vez, envia uma SELECT
consulta ao banco de dados Northwind.
Lembre-se de que, quando criamos os TableAdapters na DAL em nosso primeiro tutorial, o Visual Studio adicionou automaticamente métodos para inserir, atualizar e excluir dados da tabela de banco de dados subjacente. Além disso, em Criando uma camada lógica de negócios, projetamos métodos na BLL que chamaram esses métodos DAL de modificação de dados.
Além de seu Select()
método, o ObjectDataSource também tem Insert()
métodos , Update()
, e Delete()
. Como o Select()
método, esses três métodos podem ser mapeados para métodos em um objeto subjacente. Quando configurados para inserir, atualizar ou excluir dados, os controles GridView, DetailsView e FormView fornecem uma interface do usuário para modificar os dados subjacentes. Essa interface do usuário chama os Insert()
métodos , Update()
e do Delete()
ObjectDataSource, que invocam os métodos associados do objeto subjacente (consulte a Figura 1).
Figura 1: Os métodos , Update()
e Insert()
e Delete()
do ObjectDataSource servem como um proxy na BLL (clique para exibir a imagem em tamanho real)
Neste tutorial, veremos como mapear os métodos , Update()
e Delete()
do ObjectDataSource Insert()
para métodos de classes na BLL, bem como configurar os controles GridView, DetailsView e FormView para fornecer recursos de modificação de dados.
Etapa 1: Criando as páginas da Web de tutoriais de inserção, atualização e exclusão
Antes de começarmos a explorar como inserir, atualizar e excluir dados, vamos primeiro dedicar um momento para criar as páginas ASP.NET em nosso projeto de site que precisaremos para este tutorial e os próximos vários. Comece adicionando uma nova pasta chamada EditInsertDelete
. Em seguida, adicione as seguintes páginas ASP.NET a essa pasta, certificando-se de associar cada página à Site.master
página mestra:
Default.aspx
Basics.aspx
DataModificationEvents.aspx
ErrorHandling.aspx
UIValidation.aspx
CustomizedUI.aspx
OptimisticConcurrency.aspx
ConfirmationOnDelete.aspx
UserLevelAccess.aspx
Figura 2: Adicionar as páginas ASP.NET para os tutoriais relacionados à modificação de dados
Como nas outras pastas, Default.aspx
na EditInsertDelete
pasta listará os tutoriais em sua seção. Lembre-se de que o SectionLevelTutorialListing.ascx
Controle de Usuário fornece essa funcionalidade. Portanto, adicione esse Controle de Usuário arrastando-o Default.aspx
do Gerenciador de Soluções para o modo de exibição Design da página.
Figura 3: Adicionar o controle de usuário a Default.aspx
(clique para exibir a SectionLevelTutorialListing.ascx
imagem em tamanho real)
Por fim, adicione as páginas como entradas ao Web.sitemap
arquivo. Especificamente, adicione a seguinte marcação após a Formatação Personalizada <siteMapNode>
:
<siteMapNode title="Editing, Inserting, and Deleting"
url="~/EditInsertDelete/Default.aspx"
description="Samples of Reports that Provide Editing, Inserting,
and Deleting Capabilities">
<siteMapNode url="~/EditInsertDelete/Basics.aspx"
title="Basics"
description="Examines the basics of data modification with the
GridView, DetailsView, and FormView controls." />
<siteMapNode url="~/EditInsertDelete/DataModificationEvents.aspx"
title="Data Modification Events"
description="Explores the events raised by the ObjectDataSource
pertinent to data modification." />
<siteMapNode url="~/EditInsertDelete/ErrorHandling.aspx"
title="Error Handling"
description="Learn how to gracefully handle exceptions raised
during the data modification workflow." />
<siteMapNode url="~/EditInsertDelete/UIValidation.aspx"
title="Adding Data Entry Validation"
description="Help prevent data entry errors by providing validation." />
<siteMapNode url="~/EditInsertDelete/CustomizedUI.aspx"
title="Customize the User Interface"
description="Customize the editing and inserting user interfaces." />
<siteMapNode url="~/EditInsertDelete/OptimisticConcurrency.aspx"
title="Optimistic Concurrency"
description="Learn how to help prevent simultaneous users from
overwritting one another s changes." />
<siteMapNode url="~/EditInsertDelete/ConfirmationOnDelete.aspx"
title="Confirm On Delete"
description="Prompt a user for confirmation when deleting a record." />
<siteMapNode url="~/EditInsertDelete/UserLevelAccess.aspx"
title="Limit Capabilities Based on User"
description="Learn how to limit the data modification functionality
based on the user role or permissions." />
</siteMapNode>
Após a atualização Web.sitemap
, reserve um momento para visualizar o site de tutoriais por meio de um navegador. O menu à esquerda agora inclui itens para os tutoriais de edição, inserção e exclusão.
Figura 4: O mapa do site agora inclui entradas para os tutoriais de edição, inserção e exclusão
Etapa 2: Adicionando e configurando o controle ObjectDataSource
Como o GridView, o DetailsView e o FormView diferem em seus recursos de modificação de dados e layout, vamos examinar cada um individualmente. No entanto, em vez de ter cada controle usando seu próprio ObjectDataSource, vamos apenas criar um único ObjectDataSource que todos os três exemplos de controle possam compartilhar.
Abra a Basics.aspx
página, arraste um ObjectDataSource da Caixa de Ferramentas para o Designer e clique no link Configurar Fonte de Dados de sua marca inteligente. Como a ProductsBLL
é a única classe BLL que fornece métodos de edição, inserção e exclusão, configure o ObjectDataSource para usar essa classe.
Figura 5: Configurar o ObjectDataSource para usar a classe (clique para exibir a ProductsBLL
imagem em tamanho completo)
Na próxima tela, podemos especificar quais métodos da ProductsBLL
classe são mapeados para o , Insert()
, Update()
, do ObjectDataSource Select()
e Delete()
selecionando a guia apropriada e escolhendo o método na lista suspensa. A Figura 6, que deve parecer familiar agora, mapeia o método do Select()
ObjectDataSource para o ProductsBLL
método da GetProducts()
classe. Os Insert()
métodos , Update()
, e podem Delete()
ser configurados selecionando a guia apropriada na lista na parte superior.
Figura 6: Fazer com que o ObjectDataSource retorne todos os produtos (clique para exibir a imagem em tamanho real)
As Figuras 7, 8 e 9 mostram as guias UPDATE, INSERT e DELETE do ObjectDataSource. Configure essas guias para que os Insert()
métodos , Update()
, e Delete()
invoquem os métodos , AddProduct
, e DeleteProduct
da ProductsBLL
UpdateProduct
classe, respectivamente.
Figura 7: Mapear o método do Update()
ObjectDataSource para o método da UpdateProduct
classe (clique para exibir a ProductBLL
imagem em tamanho real)
Figura 8: Mapear o método do Insert()
ObjectDataSource para o método Add Product
da classe (clique para exibir a ProductBLL
imagem em tamanho real)
Figura 9: Mapear o método do Delete()
ObjectDataSource para o método da DeleteProduct
classe (clique para exibir a ProductBLL
imagem em tamanho real)
Você deve ter notado que as listas suspensas nas guias UPDATE, INSERT e DELETE já tinham esses métodos selecionados. Isso se deve ao nosso uso do que decora DataObjectMethodAttribute
os métodos de ProductsBLL
. Por exemplo, o método DeleteProduct tem a seguinte assinatura:
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Delete, true)]
public bool DeleteProduct(int productID)
{
...
}
O DataObjectMethodAttribute
atributo indica a finalidade de cada método, seja para selecionar, inserir, atualizar ou excluir e se é ou não o valor padrão. Se você omitiu esses atributos ao criar suas classes BLL, precisará selecionar manualmente os métodos nas guias UPDATE, INSERT e DELETE.
Depois de garantir que os métodos apropriados ProductsBLL
Insert()
sejam mapeados para os métodos , Update()
e Delete()
do ObjectDataSource, clique em Concluir para concluir o assistente.
Examinando a marcação do ObjectDataSource
Depois de configurar o ObjectDataSource por meio de seu assistente, vá para o modo de exibição Origem para examinar a marcação declarativa gerada. A <asp:ObjectDataSource>
tag especifica o objeto subjacente e os métodos a serem invocados. Além disso, há DeleteParameters
, UpdateParameters
, e InsertParameters
que mapeiam AddProduct
para os parâmetros de entrada para os ProductsBLL
métodos , UpdateProduct
, e DeleteProduct
da classe:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
DeleteMethod="DeleteProduct" InsertMethod="AddProduct"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetProducts"
TypeName="ProductsBLL" UpdateMethod="UpdateProduct">
<DeleteParameters>
<asp:Parameter Name="productID" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<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" />
<asp:Parameter Name="productID" Type="Int32" />
</UpdateParameters>
<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>
O ObjectDataSource inclui um parâmetro para cada um dos parâmetros de entrada para seus métodos associados, assim como uma lista de SelectParameter
s está presente quando o ObjectDataSource é configurado para chamar um método select que espera um parâmetro de entrada (como GetProductsByCategoryID(categoryID)
). Como veremos em breve, os valores para esses DeleteParameters
, , e InsertParameters
são definidos automaticamente pelo GridView, DetailsView e FormView antes de invocar o método , Update()
, ou Delete()
do ObjectDataSourceInsert()
UpdateParameters
. Esses valores também podem ser definidos programaticamente conforme necessário, conforme discutiremos em um tutorial futuro.
Um efeito colateral de usar o assistente para configurar como ObjectDataSource é que o Visual Studio define a propriedade OldValuesParameterFormatString como original_{0}
. Esse valor de propriedade é usado para incluir os valores originais dos dados que estão sendo editados e é útil em dois cenários:
- Se, ao editar um registro, os usuários puderem alterar o valor da chave primária. Nesse caso, o novo valor da chave primária e o valor da chave primária original devem ser fornecidos para que o registro com o valor da chave primária original possa ser encontrado e ter seu valor atualizado de acordo.
- Ao usar a simultaneidade otimista. A simultaneidade otimista é uma técnica para garantir que dois usuários simultâneos não substituam as alterações um do outro e é o tópico de um tutorial futuro.
A OldValuesParameterFormatString
propriedade indica o nome dos parâmetros de entrada nos métodos update e delete do objeto subjacente para os valores originais. Discutiremos essa propriedade e sua finalidade com mais detalhes quando explorarmos a simultaneidade otimista. Eu trago isso à tona agora, no entanto, porque os métodos de nossa BLL não esperam os valores originais e, portanto, é importante que removamos essa propriedade. Deixar a OldValuesParameterFormatString
propriedade definida como algo diferente do padrão ({0}
) causará um erro quando um controle Web de dados tentar invocar os métodos or Delete()
do ObjectDataSource, pois o ObjectDataSource tentará passar os UpdateParameters
parâmetros de valor ou DeleteParameters
especificados Update()
e originais.
Se isso não estiver muito claro neste momento, não se preocupe, examinaremos essa propriedade e sua utilidade em um tutorial futuro. Por enquanto, certifique-se de remover essa declaração de propriedade inteiramente da sintaxe declarativa ou definir o valor como o valor padrão ({0}).
Observação
Se você simplesmente limpar o OldValuesParameterFormatString
valor da propriedade da janela Propriedades no modo Design, a propriedade ainda existirá na sintaxe declarativa, mas será definida como uma cadeia de caracteres vazia. Isso, infelizmente, ainda resultará no mesmo problema discutido acima. Portanto, remova a propriedade completamente da sintaxe declarativa ou, na janela Propriedades, defina o valor como o padrão, {0}
.
Etapa 3: Adicionando um controle da Web de dados e configurando-o para modificação de dados
Depois que o ObjectDataSource for adicionado à página e configurado, estaremos prontos para adicionar controles Web de dados à página para exibir os dados e fornecer um meio para o usuário final modificá-los. Examinaremos o GridView, o DetailsView e o FormView separadamente, pois esses controles Web de dados diferem em seus recursos e configuração de modificação de dados.
Como veremos no restante deste artigo, adicionar suporte básico para edição, inserção e exclusão por meio dos controles GridView, DetailsView e FormView é realmente tão simples quanto marcar algumas caixas de seleção. Existem muitas sutilezas e casos extremos no mundo real que tornam o fornecimento dessa funcionalidade mais complicado do que apenas apontar e clicar. Este tutorial, no entanto, se concentra apenas em provar recursos simplistas de modificação de dados. Tutoriais futuros examinarão preocupações que, sem dúvida, surgirão em um cenário do mundo real.
Excluindo dados do GridView
Comece arrastando um GridView da Caixa de Ferramentas para o Designer. Em seguida, associe o ObjectDataSource ao GridView selecionando-o na lista suspensa na marca inteligente do GridView. Neste ponto, a marcação declarativa do GridView será:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
<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>
Associar o GridView ao ObjectDataSource por meio de sua marca inteligente tem dois benefícios:
- BoundFields e CheckBoxFields são criados automaticamente para cada um dos campos retornados pelo ObjectDataSource. Além disso, as propriedades de BoundField e CheckBoxField são definidas com base nos metadados do campo subjacente. Por exemplo, os
ProductID
campos ,CategoryName
eSupplierName
são marcados como somente leitura no e, portanto, não devem ser atualizáveis durante aProductsDataTable
edição. Para acomodar isso, as propriedades ReadOnly desses BoundFields são definidas comotrue
. - A propriedade DataKeyNames é atribuída ao(s) campo(s) de chave primária do objeto subjacente. Isso é essencial ao usar o GridView para editar ou excluir dados, pois essa propriedade indica o campo (ou conjunto de campos) que identifica exclusivamente cada registro. Para obter mais informações sobre a
DataKeyNames
propriedade, consulte o tutorial Mestre/Detalhe usando um GridView mestre selecionável com um detalhe de detalhes.
Embora o GridView possa ser associado ao ObjectDataSource por meio da janela Propriedades ou da sintaxe declarativa, isso requer que você adicione manualmente o BoundField e DataKeyNames
a marcação apropriados.
O controle GridView fornece suporte interno para edição e exclusão em nível de linha. Configurar um GridView para dar suporte à exclusão adiciona uma coluna de botões Excluir. Quando o usuário final clica no botão Excluir para uma linha específica, um postback ocorre e o GridView executa as seguintes etapas:
- Os valores do
DeleteParameters
ObjectDataSource são atribuídos - O método do
Delete()
ObjectDataSource é invocado, excluindo o registro especificado - O GridView se associa novamente ao ObjectDataSource invocando seu
Select()
método
Os valores atribuídos ao DeleteParameters
são os valores do DataKeyNames
(s) campo(s) da linha cujo botão Excluir foi clicado. Portanto, é vital que a propriedade de DataKeyNames
um GridView seja definida corretamente. Se estiver ausente, será DeleteParameters
atribuído um null
valor na Etapa 1, o que, por sua vez, não resultará em nenhum registro excluído na Etapa 2.
Observação
A DataKeys
coleção é armazenada no estado de controle do GridView, o que significa que os DataKeys
valores serão lembrados no postback, mesmo que o estado de exibição do GridView tenha sido desabilitado. No entanto, é muito importante que o estado de exibição permaneça habilitado para GridViews que dão suporte à edição ou exclusão (o comportamento padrão). Se você definir a propriedade do GridView como false
, o comportamento de edição e exclusão funcionará bem para um único usuário, mas se houver usuários simultâneos excluindo dados, existe a possibilidade de que esses usuários simultâneos EnableViewState
possam excluir ou editar acidentalmente registros que não pretendiam.
Esse mesmo aviso também se aplica a DetailsViews e FormViews.
Para adicionar recursos de exclusão a um GridView, basta acessar sua marca inteligente e marcar a caixa de seleção Habilitar exclusão.
Figura 10: Marque a caixa de seleção Habilitar exclusão
Marcar a caixa de seleção Habilitar Exclusão na marca inteligente adiciona um CommandField ao GridView. O CommandField renderiza uma coluna no GridView com botões para executar uma ou mais das seguintes tarefas: selecionar um registro, editar um registro e excluir um registro. Anteriormente, vimos o CommandField em ação com a seleção de registros no tutorial Mestre/Detalhe Usando um GridView Mestre Selecionável com um DetailView de Detalhes.
O CommandField contém várias ShowXButton
propriedades que indicam quais séries de botões são exibidas no CommandField. Ao marcar a caixa de seleção Habilitar Exclusão, um CommandField cuja ShowDeleteButton
propriedade é true
foi adicionado à coleção Columns do GridView.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
<Columns>
<asp:CommandField ShowDeleteButton="True" />
... BoundFields removed for brevity ...
</Columns>
</asp:GridView>
Neste ponto, acredite ou não, terminamos de adicionar suporte à exclusão do GridView! Como mostra a Figura 11, ao visitar esta página por meio de um navegador, uma coluna de botões Delete está presente.
Figura 11: O CommandField adiciona uma coluna de botões de exclusão (clique para exibir a imagem em tamanho real)
Se você está construindo este tutorial do zero por conta própria, ao testar esta página, clicar no botão Excluir gerará uma exceção. Continue lendo para saber por que essas exceções foram levantadas e como corrigi-las.
Observação
Se você estiver acompanhando usando o download que acompanha este tutorial, esses problemas já foram contabilizados. No entanto, encorajo você a ler os detalhes listados abaixo para ajudar a identificar problemas que possam surgir e soluções alternativas adequadas.
Se, ao tentar excluir um produto, você receber uma exceção cuja mensagem é semelhante a "ObjectDataSource 'ObjectDataSource1' não foi possível encontrar um método não genérico 'DeleteProduct' que tenha parâmetros: productID, original_ProductID", provavelmente esqueceu de remover a OldValuesParameterFormatString
propriedade do ObjectDataSource. Com a OldValuesParameterFormatString
propriedade especificada, o ObjectDataSource tenta passar os productID
parâmetros de entrada e original_ProductID
os parâmetros para o DeleteProduct
método. DeleteProduct
, no entanto, aceita apenas um único parâmetro de entrada, daí a exceção. Remover a OldValuesParameterFormatString
propriedade (ou defini-la como {0}
) instrui o ObjectDataSource a não tentar passar o parâmetro de entrada original.
Figura 12: Verifique se a OldValuesParameterFormatString
propriedade foi limpa (clique para exibir a imagem em tamanho real)
Mesmo que você tenha removido a OldValuesParameterFormatString
propriedade, ainda receberá uma exceção ao tentar excluir um produto com a mensagem: "A instrução DELETE entrou em conflito com a restrição REFERENCE 'FK_Order_Details_Products'". O banco de dados Northwind contém uma restrição de chave estrangeira entre a tabela eProducts
, o Order Details
que significa que um produto não pode ser excluído do sistema se houver um ou mais registros para ele na Order Details
tabela. Como cada produto no banco de dados Northwind tem pelo menos um registro no Order Details
, não podemos excluir nenhum produto até que primeiro excluamos os registros de detalhes do pedido associados ao produto.
Figura 13: Uma restrição de chave estrangeira proíbe a exclusão de produtos (clique para exibir a imagem em tamanho real)
Para o nosso tutorial, vamos excluir todos os registros da Order Details
tabela. Em uma aplicação do mundo real, precisaríamos:
- Tenha outra tela para gerenciar as informações de detalhes do pedido
- Aumente o
DeleteProduct
método para incluir lógica para excluir os detalhes do pedido do produto especificado - Modifique a consulta SQL usada pelo TableAdapter para incluir a exclusão dos detalhes do pedido do produto especificado
Vamos excluir todos os registros da Order Details
tabela para contornar a restrição de chave estrangeira. Vá para o Gerenciador de Servidores no Visual Studio, clique com o botão direito do NORTHWND.MDF
mouse no nó e escolha Nova Consulta. Em seguida, na janela de consulta, execute a seguinte instrução SQL: DELETE FROM [Order Details]
Figura 14: Excluir todos os registros da tabela (clique para exibir a Order Details
imagem em tamanho real)
Depois de limpar a Order Details
tabela, clicar no botão Excluir excluirá o produto sem erros. Se clicar no botão Excluir não excluir o produto, verifique se a propriedade do GridView DataKeyNames
está definida como o campo de chave primária (ProductID
).
Observação
Ao clicar no botão Excluir, ocorre um postback e o registro é excluído. Isso pode ser perigoso, pois é fácil clicar acidentalmente no botão Excluir da linha errada. Em um tutorial futuro, veremos como adicionar uma confirmação do lado do cliente ao excluir um registro.
Editando dados com o GridView
Além da exclusão, o controle GridView também fornece suporte interno à edição em nível de linha. Configurar um GridView para dar suporte à edição adiciona uma coluna de botões Editar. Do ponto de vista do usuário final, clicar no botão Editar de uma linha faz com que essa linha se torne editável, transformando as células em caixas de texto contendo os valores existentes e substituindo o botão Editar pelos botões Atualizar e Cancelar. Depois de fazer as alterações desejadas, o usuário final pode clicar no botão Atualizar para confirmar as alterações ou no botão Cancelar para descartá-las. Em ambos os casos, depois de clicar em Atualizar ou Cancelar, o GridView retorna ao seu estado de pré-edição.
De nossa perspectiva como desenvolvedor de página, quando o usuário final clica no botão Editar para uma linha específica, um postback ocorre e o GridView executa as seguintes etapas:
- A propriedade do GridView
EditItemIndex
é atribuída ao índice da linha cujo botão Editar foi clicado - O GridView se associa novamente ao ObjectDataSource invocando seu
Select()
método - O índice de linha que corresponde ao
EditItemIndex
é renderizado no "modo de edição". Nesse modo, o botão Editar é substituído pelos botões Atualizar e Cancelar e BoundFields cujasReadOnly
propriedades são False (o padrão) são renderizados como controles Web TextBox cujasText
propriedades são atribuídas aos valores dos campos de dados.
Nesse ponto, a marcação é retornada ao navegador, permitindo que o usuário final faça alterações nos dados da linha. Quando o usuário clica no botão Atualizar, ocorre um postback e o GridView executa as seguintes etapas:
- Os valores do ObjectDataSource
UpdateParameters
são atribuídos aos valores inseridos pelo usuário final na interface de edição do GridView - O método do
Update()
ObjectDataSource é invocado, atualizando o registro especificado - O GridView se associa novamente ao ObjectDataSource invocando seu
Select()
método
Os valores de chave primária atribuídos à UpdateParameters
Etapa 1 vêm dos valores especificados na DataKeyNames
propriedade, enquanto os valores de chave não primária vêm do texto nos controles Web TextBox para a linha editada. Assim como acontece com a exclusão, é vital que a propriedade de DataKeyNames
um GridView seja definida corretamente. Se estiver ausente, o valor da UpdateParameters
chave primária receberá um null
valor na Etapa 1, o que, por sua vez, não resultará em nenhum registro atualizado na Etapa 2.
A funcionalidade de edição pode ser ativada simplesmente marcando a caixa de seleção Habilitar edição na marca inteligente do GridView.
Figura 15: Marque a caixa de seleção Ativar edição
Marcar a caixa de seleção Ativar edição adicionará um CommandField (se necessário) e definirá sua ShowEditButton
propriedade como true
. Como vimos anteriormente, o CommandField contém várias ShowXButton
propriedades que indicam quais séries de botões são exibidas no CommandField. Marcar a caixa de seleção Habilitar edição adiciona a ShowEditButton
propriedade ao CommandField existente:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
<Columns>
<asp:CommandField ShowDeleteButton="True"
ShowEditButton="True" />
... BoundFields removed for brevity ...
</Columns>
</asp:GridView>
Isso é tudo o que há para adicionar suporte de edição rudimentar. Como mostra a Figura 16, a interface de edição é bastante rudimentar: cada BoundField cuja ReadOnly
propriedade é definida como false
(o padrão) é renderizada como um TextBox. Isso inclui campos como CategoryID
e SupplierID
, que são chaves para outras tabelas.
Figura 16: Clicar no botão Editar do Chai exibe a linha no modo de edição (clique para exibir a imagem em tamanho real)
Além de solicitar que os usuários editem valores de chave estrangeira diretamente, a interface da interface de edição está ausente das seguintes maneiras:
- Se o usuário inserir um
CategoryID
ouSupplierID
que não existe no banco de dados, oUPDATE
violará uma restrição de chave estrangeira, fazendo com que uma exceção seja gerada. - A interface de edição não inclui nenhuma validação. Se você não fornecer um valor necessário (como
ProductName
), ou inserir um valor de cadeia de caracteres em que um valor numérico é esperado (como inserir "Demais!" naUnitPrice
caixa de texto), uma exceção será lançada. Um tutorial futuro examinará como adicionar controles de validação à interface do usuário de edição. - Atualmente, todos os campos de produto que não são somente leitura devem ser incluídos no GridView. Se removêssemos um campo do GridView, digamos
UnitPrice
, ao atualizar os dados, o GridView não definiria o valor, oUnitPrice
UpdateParameters
que alteraria o registro doUnitPrice
banco de dados para umNULL
valor. Da mesma forma, se um campo obrigatório, comoProductName
, for removido do GridView, a atualização falhará com a mesma exceção "A coluna 'ProductName' não permite nulos" mencionada acima. - A formatação da interface de edição deixa muito a desejar. O
UnitPrice
é mostrado com quatro casas decimais. Idealmente, osCategoryID
valores andSupplierID
conteriam DropDownLists que listam as categorias e fornecedores no sistema.
Todas essas são deficiências com as quais teremos que conviver por enquanto, mas serão abordadas em tutoriais futuros.
Inserindo, editando e excluindo dados com o DetailsView
Como vimos em tutoriais anteriores, o controle DetailsView exibe um registro por vez e, como o GridView, permite a edição e a exclusão do registro exibido no momento. A experiência do usuário final com a edição e exclusão de itens de um DetailsView e o fluxo de trabalho do lado ASP.NET é idêntico ao do GridView. Onde o DetailsView difere do GridView é que ele também fornece suporte de inserção interno.
Para demonstrar os recursos de modificação de dados do GridView, comece adicionando um DetailsView à Basics.aspx
página acima do GridView existente e associe-o ao ObjectDataSource existente por meio da marca inteligente do DetailsView. Em seguida, limpe Width
as propriedades e Height
DetailsView e marque a opção Habilitar paginação na marca inteligente. Para habilitar o suporte à edição, inserção e exclusão, basta marcar as caixas de seleção Habilitar edição, Habilitar inserção e Habilitar exclusão na marca inteligente.
Figura 17: Configurar o DetailsView para dar suporte à edição, inserção e exclusão
Assim como acontece com o GridView, adicionar suporte à edição, inserção ou exclusão adiciona um CommandField ao DetailsView, como mostra a sintaxe declarativa a seguir:
<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True">
<Fields>
<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" />
<asp:CommandField ShowDeleteButton="True"
ShowEditButton="True" ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
Observe que, para o DetailsView, o CommandField aparece no final da coleção Columns por padrão. Como os campos do DetailsView são renderizados como linhas, o CommandField aparece como uma linha com os botões Inserir, Editar e Excluir na parte inferior do DetailsView.
Figura 18: Configurar o DetailsView para dar suporte à edição, inserção e exclusão (clique para exibir a imagem em tamanho real)
Clicar no botão Excluir inicia a mesma sequência de eventos do GridView: um postback; seguido pelo DetailsView preenchendo seu ObjectDataSource DeleteParameters
com base nos DataKeyNames
valores; e concluído com uma chamada ao método do Delete()
ObjectDataSource, que na verdade remove o produto do banco de dados. A edição no DetailsView também funciona de maneira idêntica à do GridView.
Para inserir, o usuário final recebe um botão New que, quando clicado, renderiza o DetailsView no "modo de inserção". Com o "modo de inserção", o botão Novo é substituído pelos botões Inserir e Cancelar e apenas os BoundFields cuja InsertVisible
propriedade está definida como true
(o padrão) são exibidos. Os campos de dados identificados como campos de incremento automático, como ProductID
, têm sua propriedade InsertVisible definida como false
ao vincular o DetailsView à fonte de dados por meio da marca inteligente.
Ao associar uma fonte de dados a um DetailsView por meio da marca inteligente, o Visual Studio define a propriedade como false
apenas para campos de incremento InsertVisible
automático. Os campos somente leitura, como CategoryName
e SupplierName
, serão exibidos na interface do usuário do "modo de inserção", a menos que sua InsertVisible
propriedade seja explicitamente definida como false
. Reserve um momento para definir as propriedades desses dois campos InsertVisible
como false
, por meio da sintaxe declarativa do DetailsView ou por meio do link Editar campos na marca inteligente. A Figura 19 mostra a InsertVisible
configuração das propriedades para false
clicando no link Edit Fields.
Figura 19: Northwind Traders agora oferece chá Acme (clique para ver a imagem em tamanho real)
Depois de definir as InsertVisible
propriedades, exiba a Basics.aspx
página em um navegador e clique no botão Novo. A Figura 20 mostra o DetailsView ao adicionar uma nova bebida, Acme Tea, à nossa linha de produtos.
Figura 20: Northwind Traders agora oferece chá Acme (clique para ver a imagem em tamanho real)
Depois de inserir os detalhes do Acme Tea e clicar no botão Inserir, um postback ocorre e o novo registro é adicionado à tabela do Products
banco de dados. Como esse DetailsView lista os produtos na ordem em que eles existem na tabela do banco de dados, devemos paginar para o último produto para ver o novo produto.
Figura 21: Detalhes do Acme Tea (clique para ver a imagem em tamanho real)
Observação
A propriedade CurrentMode do DetailsView indica a interface que está sendo exibida e pode ser um dos seguintes valores: Edit
, Insert
, ou ReadOnly
. A propriedade DefaultMode indica o modo para o qual o DetailsView retorna após a conclusão de uma edição ou inserção e é útil para exibir um DetailsView que está permanentemente no modo de edição ou inserção.
Os recursos de inserção e edição de apontar e clicar do DetailsView sofrem das mesmas limitações que o GridView: o usuário deve inserir valores existentes CategoryID
e SupplierID
por meio de uma caixa de texto; a interface não tem nenhuma lógica de validação; todos os campos de produto que não permitem NULL
valores ou não têm um valor padrão especificado no nível do banco de dados devem ser incluídos na interface de inserção, e assim por diante.
As técnicas que examinaremos para estender e aprimorar a interface de edição do GridView em artigos futuros também podem ser aplicadas às interfaces de edição e inserção do controle DetailsView.
Usando o FormView para uma interface de usuário de modificação de dados mais flexível
O FormView oferece suporte interno para inserir, editar e excluir dados, mas como ele usa modelos em vez de campos, não há lugar para adicionar o BoundFields ou o CommandField usado pelos controles GridView e DetailsView para fornecer a interface de modificação de dados. Em vez disso, essa interface com os controles da Web para coletar a entrada do usuário ao adicionar um novo item ou editar um existente, juntamente com os botões Novo, Editar, Excluir, Inserir, Atualizar e Cancelar deve ser adicionada manualmente aos modelos apropriados. Felizmente, o Visual Studio criará automaticamente a interface necessária ao associar o FormView a uma fonte de dados por meio da lista suspensa em sua marca inteligente.
Para ilustrar essas técnicas, comece adicionando um FormView à Basics.aspx
página e, na marca inteligente do FormView, vincule-o ao ObjectDataSource já criado. Isso gerará um EditItemTemplate
, InsertItemTemplate
e ItemTemplate
para o FormView com controles Web TextBox para coletar a entrada do usuário e controles Web de botão para os botões Novo, Editar, Excluir, Inserir, Atualizar e Cancelar. Além disso, a propriedade do DataKeyNames
FormView é definida como o campo de chave primária (ProductID
) do objeto retornado pelo ObjectDataSource. Por fim, marque a opção Ativar paginação na marca inteligente do FormView.
O exemplo a seguir mostra a marcação declarativa para o FormView depois que ItemTemplate
o FormView foi associado ao ObjectDataSource. Por padrão, cada campo de produto de valor não booliano é associado à Text
propriedade de um controle Web Rótulo, enquanto cada campo de valor booliano (Discontinued
) é associado à Checked
propriedade de um controle Web CheckBox desabilitado. Para que os botões Novo, Editar e Excluir disparem determinado comportamento do FormView quando clicados, é imperativo que seus CommandName
valores sejam definidos como New
, Edit
e Delete
, respectivamente.
<asp:FormView ID="FormView1" runat="server" DataKeyNames="ProductID"
DataSourceID="ObjectDataSource1" AllowPaging="True">
<EditItemTemplate>
...
</EditItemTemplate>
<InsertItemTemplate>
...
</InsertItemTemplate>
<ItemTemplate>
ProductID:
<asp:Label ID="ProductIDLabel" runat="server"
Text='<%# Eval("ProductID") %>'></asp:Label><br />
ProductName:
<asp:Label ID="ProductNameLabel" runat="server"
Text='<%# Bind("ProductName") %>'>
</asp:Label><br />
SupplierID:
<asp:Label ID="SupplierIDLabel" runat="server"
Text='<%# Bind("SupplierID") %>'>
</asp:Label><br />
CategoryID:
<asp:Label ID="CategoryIDLabel" runat="server"
Text='<%# Bind("CategoryID") %>'>
</asp:Label><br />
QuantityPerUnit:
<asp:Label ID="QuantityPerUnitLabel" runat="server"
Text='<%# Bind("QuantityPerUnit") %>'>
</asp:Label><br />
UnitPrice:
<asp:Label ID="UnitPriceLabel" runat="server"
Text='<%# Bind("UnitPrice") %>'></asp:Label><br />
UnitsInStock:
<asp:Label ID="UnitsInStockLabel" runat="server"
Text='<%# Bind("UnitsInStock") %>'>
</asp:Label><br />
UnitsOnOrder:
<asp:Label ID="UnitsOnOrderLabel" runat="server"
Text='<%# Bind("UnitsOnOrder") %>'>
</asp:Label><br />
ReorderLevel:
<asp:Label ID="ReorderLevelLabel" runat="server"
Text='<%# Bind("ReorderLevel") %>'>
</asp:Label><br />
Discontinued:
<asp:CheckBox ID="DiscontinuedCheckBox" runat="server"
Checked='<%# Bind("Discontinued") %>'
Enabled="false" /><br />
CategoryName:
<asp:Label ID="CategoryNameLabel" runat="server"
Text='<%# Bind("CategoryName") %>'>
</asp:Label><br />
SupplierName:
<asp:Label ID="SupplierNameLabel" runat="server"
Text='<%# Bind("SupplierName") %>'>
</asp:Label><br />
<asp:LinkButton ID="EditButton" runat="server"
CausesValidation="False" CommandName="Edit"
Text="Edit">
</asp:LinkButton>
<asp:LinkButton ID="DeleteButton" runat="server"
CausesValidation="False" CommandName="Delete"
Text="Delete">
</asp:LinkButton>
<asp:LinkButton ID="NewButton" runat="server"
CausesValidation="False" CommandName="New"
Text="New">
</asp:LinkButton>
</ItemTemplate>
</asp:FormView>
A Figura 22 mostra o FormView quando visualizado por meio de ItemTemplate
um navegador. Cada campo de produto é listado com os botões Novo, Editar e Excluir na parte inferior.
Figura 22: O Defaut FormView ItemTemplate
lista cada campo de produto junto com os botões Novo, Editar e Excluir (clique para exibir a imagem em tamanho real)
Assim como acontece com o GridView e o DetailsView, clicar no botão Excluir ou em qualquer Button, LinkButton ou ImageButton cuja CommandName
propriedade esteja definida como Delete causa um postback, preenche o ObjectDataSource DeleteParameters
com base no valor do DataKeyNames
FormView e invoca o método do Delete()
ObjectDataSource.
Quando o botão Editar é clicado, um postback ocorre e os dados são recuperados para o EditItemTemplate
, que é responsável por renderizar a interface de edição. Essa interface inclui os controles da Web para editar dados junto com os botões Atualizar e Cancelar. O padrão EditItemTemplate
gerado pelo Visual Studio contém um Label para qualquer campo de incremento automático (ProductID
), um TextBox para cada campo de valor não booliano e um CheckBox para cada campo de valor booliano. Esse comportamento é muito semelhante aos BoundFields gerados automaticamente nos controles GridView e DetailsView.
Observação
Um pequeno problema com a EditItemTemplate
geração automática do FormView é que ele renderiza controles Web TextBox para os campos que são somente leitura, como CategoryName
e SupplierName
. Veremos como explicar isso em breve.
Os controles TextBox no EditItemTemplate
têm sua Text
propriedade associada ao valor do campo de dados correspondente usando a ligação de dados bidirecional. A vinculação de dados bidirecional, indicada por <%# Bind("dataField") %>
, executa a vinculação de dados ao vincular dados ao modelo e ao preencher os parâmetros do ObjectDataSource para inserir ou editar registros. Ou seja, quando o usuário clica no botão Editar do , o Bind()
método retorna o valor do campo de ItemTemplate
dados especificado. Depois que o usuário faz suas alterações e clica em Atualizar, os valores postados de volta que correspondem aos campos de dados especificados UpdateParameters
usando Bind()
são aplicados ao arquivo . Como alternativa, a vinculação de dados unidirecional, indicada por <%# Eval("dataField") %>
, recupera apenas os valores do campo de dados ao vincular dados ao modelo e não retorna os valores inseridos pelo usuário aos parâmetros da fonte de dados no postback.
A marcação declarativa a seguir mostra o EditItemTemplate
arquivo . Observe que o Bind()
método é usado na sintaxe de vinculação de dados aqui e que os controles Web Botão Atualizar e Cancelar têm suas CommandName
propriedades definidas adequadamente.
<asp:FormView ID="FormView1" runat="server" DataKeyNames="ProductID"
DataSourceID="ObjectDataSource1" AllowPaging="True">
<EditItemTemplate>
ProductID:
<asp:Label ID="ProductIDLabel1" runat="server"
Text="<%# Eval("ProductID") %>"></asp:Label><br />
ProductName:
<asp:TextBox ID="ProductNameTextBox" runat="server"
Text="<%# Bind("ProductName") %>">
</asp:TextBox><br />
SupplierID:
<asp:TextBox ID="SupplierIDTextBox" runat="server"
Text="<%# Bind("SupplierID") %>">
</asp:TextBox><br />
CategoryID:
<asp:TextBox ID="CategoryIDTextBox" runat="server"
Text="<%# Bind("CategoryID") %>">
</asp:TextBox><br />
QuantityPerUnit:
<asp:TextBox ID="QuantityPerUnitTextBox" runat="server"
Text="<%# Bind("QuantityPerUnit") %>">
</asp:TextBox><br />
UnitPrice:
<asp:TextBox ID="UnitPriceTextBox" runat="server"
Text="<%# Bind("UnitPrice") %>">
</asp:TextBox><br />
UnitsInStock:
<asp:TextBox ID="UnitsInStockTextBox" runat="server"
Text="<%# Bind("UnitsInStock") %>">
</asp:TextBox><br />
UnitsOnOrder:
<asp:TextBox ID="UnitsOnOrderTextBox" runat="server"
Text="<%# Bind("UnitsOnOrder") %>">
</asp:TextBox><br />
ReorderLevel:
<asp:TextBox ID="ReorderLevelTextBox" runat="server"
Text="<%# Bind("ReorderLevel") %>">
</asp:TextBox><br />
Discontinued:
<asp:CheckBox ID="DiscontinuedCheckBox" runat="server"
Checked="<%# Bind("Discontinued") %>" /><br />
CategoryName:
<asp:TextBox ID="CategoryNameTextBox" runat="server"
Text="<%# Bind("CategoryName") %>">
</asp:TextBox><br />
SupplierName:
<asp:TextBox ID="SupplierNameTextBox" runat="server"
Text="<%# Bind("SupplierName") %>">
</asp:TextBox><br />
<asp:LinkButton ID="UpdateButton" runat="server"
CausesValidation="True" CommandName="Update"
Text="Update">
</asp:LinkButton>
<asp:LinkButton ID="UpdateCancelButton" runat="server"
CausesValidation="False" CommandName="Cancel"
Text="Cancel">
</asp:LinkButton>
</EditItemTemplate>
<InsertItemTemplate>
...
</InsertItemTemplate>
<ItemTemplate>
...
</ItemTemplate>
</asp:FormView>
Nosso EditItemTemplate
, neste ponto, fará com que uma exceção seja lançada se tentarmos usá-lo. O problema é que os CategoryName
campos e SupplierName
são renderizados como controles Web TextBox no EditItemTemplate
. Precisamos alterar essas TextBoxes para Labels ou removê-las completamente. Vamos simplesmente excluí-los completamente do EditItemTemplate
.
A Figura 23 mostra o FormView em um navegador depois que o botão Edit foi clicado para Chai. Observe que os SupplierName
campos e CategoryName
mostrados no não ItemTemplate
estão mais presentes, pois acabamos de removê-los do EditItemTemplate
. Quando o botão Atualizar é clicado, o FormView prossegue pela mesma sequência de etapas que os controles GridView e DetailsView.
Figura 23: Por padrão, o EditItemTemplate
mostra cada campo de produto editável como uma caixa de texto ou caixa de seleção (clique para exibir a imagem em tamanho real)
Quando o botão Inserir é clicado, o FormView é um postback.ItemTemplate
No entanto, nenhum dado está associado ao FormView porque um novo registro está sendo adicionado. A InsertItemTemplate
interface inclui os controles da Web para adicionar um novo registro junto com os botões Inserir e Cancelar. O padrão InsertItemTemplate
gerado pelo Visual Studio contém um TextBox para cada campo de valor não booliano e um CheckBox para cada campo de valor booliano, semelhante à interface do gerado EditItemTemplate
automaticamente. Os controles TextBox têm sua Text
propriedade associada ao valor de seu campo de dados correspondente usando vinculação de dados bidirecional.
A marcação declarativa a seguir mostra o InsertItemTemplate
arquivo . Observe que o Bind()
método é usado na sintaxe de vinculação de dados aqui e que os controles Web Inserir e Cancelar Botão têm suas CommandName
propriedades definidas adequadamente.
<asp:FormView ID="FormView1" runat="server" DataKeyNames="ProductID"
DataSourceID="ObjectDataSource1" AllowPaging="True">
<EditItemTemplate>
...
</EditItemTemplate>
<InsertItemTemplate>
ProductName:
<asp:TextBox ID="ProductNameTextBox" runat="server"
Text="<%# Bind("ProductName") %>">
</asp:TextBox><br />
SupplierID:
<asp:TextBox ID="SupplierIDTextBox" runat="server"
Text="<%# Bind("SupplierID") %>">
</asp:TextBox><br />
CategoryID:
<asp:TextBox ID="CategoryIDTextBox" runat="server"
Text="<%# Bind("CategoryID") %>">
</asp:TextBox><br />
QuantityPerUnit:
<asp:TextBox ID="QuantityPerUnitTextBox" runat="server"
Text="<%# Bind("QuantityPerUnit") %>">
</asp:TextBox><br />
UnitPrice:
<asp:TextBox ID="UnitPriceTextBox" runat="server"
Text="<%# Bind("UnitPrice") %>">
</asp:TextBox><br />
UnitsInStock:
<asp:TextBox ID="UnitsInStockTextBox" runat="server"
Text="<%# Bind("UnitsInStock") %>">
</asp:TextBox><br />
UnitsOnOrder:
<asp:TextBox ID="UnitsOnOrderTextBox" runat="server"
Text="<%# Bind("UnitsOnOrder") %>">
</asp:TextBox><br />
ReorderLevel:
<asp:TextBox ID="ReorderLevelTextBox" runat="server"
Text="<%# Bind("ReorderLevel") %>">
</asp:TextBox><br />
Discontinued:
<asp:CheckBox ID="DiscontinuedCheckBox" runat="server"
Checked="<%# Bind("Discontinued") %>" /><br />
CategoryName:
<asp:TextBox ID="CategoryNameTextBox" runat="server"
Text="<%# Bind("CategoryName") %>">
</asp:TextBox><br />
SupplierName:
<asp:TextBox ID="SupplierNameTextBox" runat="server"
Text="<%# Bind("SupplierName") %>">
</asp:TextBox><br />
<asp:LinkButton ID="InsertButton" runat="server"
CausesValidation="True" CommandName="Insert"
Text="Insert">
</asp:LinkButton>
<asp:LinkButton ID="InsertCancelButton" runat="server"
CausesValidation="False" CommandName="Cancel"
Text="Cancel">
</asp:LinkButton>
</InsertItemTemplate>
<ItemTemplate>
...
</ItemTemplate>
</asp:FormView>
Há uma sutileza com a geração automática do FormView do InsertItemTemplate
. Especificamente, os controles Web TextBox são criados até mesmo para os campos somente leitura, como CategoryName
e SupplierName
. Assim como no EditItemTemplate
, precisamos remover essas TextBoxes do InsertItemTemplate
.
A Figura 24 mostra o FormView em um navegador ao adicionar um novo produto, Acme Coffee. Observe que os SupplierName
campos e CategoryName
mostrados no ItemTemplate
não estão mais presentes, pois acabamos de removê-los. Quando o botão Inserir é clicado, o FormView prossegue com a mesma sequência de etapas que o controle DetailsView, adicionando um novo registro à Products
tabela. A Figura 25 mostra os detalhes do produto Acme Coffee no FormView depois que ele foi inserido.
Figura 24: O InsertItemTemplate
dita a interface de inserção do FormView (clique para exibir a imagem em tamanho real)
Figura 25: Os detalhes do novo produto, Acme Coffee, são exibidos no FormView (clique para exibir a imagem em tamanho real)
Ao separar as interfaces somente leitura, edição e inserção em três modelos separados, o FormView permite um grau mais refinado de controle sobre essas interfaces do que o DetailsView e o GridView.
Observação
Assim como o DetailsView, a propriedade do CurrentMode
FormView indica a interface que está sendo exibida e sua DefaultMode
propriedade indica o modo para o qual o FormView retorna após a conclusão de uma edição ou inserção.
Resumo
Neste tutorial, examinamos os conceitos básicos de inserção, edição e exclusão de dados usando o GridView, o DetailsView e o FormView. Todos esses três controles fornecem algum nível de recursos internos de modificação de dados que podem ser utilizados sem escrever uma única linha de código na página ASP.NET, graças aos controles Web de dados e ao ObjectDataSource. No entanto, as técnicas simples de apontar e clicar renderizam uma interface de usuário de modificação de dados bastante frágil e ingênua. Para fornecer validação, injetar valores programáticos, lidar com exceções normalmente, personalizar a interface do usuário e assim por diante, precisaremos contar com um bando de técnicas que serão discutidas nos próximos tutoriais.
Boa programação!
Sobre o autor
Scott Mitchell, autor de sete livros ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Web da Microsoft desde 1998. Scott trabalha como consultor, instrutor e escritor independente. 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.