Compartilhar via


Uma visão geral da inserção, atualização e exclusão de dados (C#)

por Scott Mitchell

Baixar PDF

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

Os métodos insert(), update() e delete() do ObjectDataSource servem como um proxy para a BLL

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

Adicione as páginas ASP.NET para os tutoriais relacionados à modificação de dados

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.

Adicione o controle de usuário SectionLevelTutorialListing.ascx a Default.aspx

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.

O mapa do site agora inclui entradas 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.

Configurar o ObjectDataSource para usar a classe ProductsBLL

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.

Faça com que o ObjectDataSource retorne todos os produtos

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 UpdateProductclasse, respectivamente.

Mapeie o método Update() do ObjectDataSource para o método UpdateProduct da classe ProductBLL

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)

Mapeie o método Insert() do ObjectDataSource para o método AddProduct da classe ProductBLL

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)

Mapeie o método Delete() do ObjectDataSource para o método DeleteProduct da classe ProductBLL

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 AddProductpara 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 ProductIDcampos , CategoryNamee SupplierName são marcados como somente leitura no e, portanto, não devem ser atualizáveis durante a ProductsDataTable edição. Para acomodar isso, as propriedades ReadOnly desses BoundFields são definidas como true.
  • 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:

  1. Os valores do DeleteParameters ObjectDataSource são atribuídos
  2. O método do Delete() ObjectDataSource é invocado, excluindo o registro especificado
  3. 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.

Marque a caixa de seleção Ativar 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.

O CommandField adiciona uma coluna de botões de exclusão

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.

Verifique se a propriedade OldValuesParameterFormatString foi apagada

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.

Uma restrição de chave estrangeira proíbe a exclusão de produtos

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]

Excluir todos os registros da tabela de detalhes do pedido

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:

  1. A propriedade do GridView EditItemIndex é atribuída ao índice da linha cujo botão Editar foi clicado
  2. O GridView se associa novamente ao ObjectDataSource invocando seu Select() método
  3. 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 cujas ReadOnly propriedades são False (o padrão) são renderizados como controles Web TextBox cujas Text 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:

  1. Os valores do ObjectDataSource UpdateParameters são atribuídos aos valores inseridos pelo usuário final na interface de edição do GridView
  2. O método do Update() ObjectDataSource é invocado, atualizando o registro especificado
  3. 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.

Marque a caixa de seleção Ativar edição

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.

Clicar no botão Editar do Chai exibe a linha no modo de edição

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 ou SupplierID que não existe no banco de dados, o UPDATE 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!" na UnitPrice 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, o UnitPrice UpdateParameters que alteraria o registro do UnitPrice banco de dados para um NULL valor. Da mesma forma, se um campo obrigatório, como ProductName, 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, os CategoryID valores and SupplierID 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.

Captura de tela mostrando a janela DetailsView Tasks com as caixas de seleção Habilitar Inserção, Habilitar Edição e Habilitar Exclusão marcadas.

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.

Captura de tela do DetailsView com o CommandField aparecendo como uma linha inferior com os botões Inserir, Editar e Excluir.

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.

Captura de tela mostrando a janela Campos com a propriedade InsertVisible definida como False.

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.

Captura de tela mostrando o DetailsView da página Basics.aspx em um navegador da Web.

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.

Detalhes de Acme Tea

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, InsertItemTemplatee 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, Edite 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.

O ItemTemplate do Defaut FormView lista cada campo de produto junto com os botões novo, editar e excluir

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 ItemTemplatedados 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 UpdateParametersusando 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 EditItemTemplatearquivo . 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.

Por padrão, o EditItemTemplate mostra cada campo de produto editável como um TextBox ou CheckBox

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 EditItemTemplateautomaticamente. 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 InsertItemTemplatearquivo . 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.

O InsertItemTemplate dita a interface de inserção do FormView

Figura 24: O InsertItemTemplate dita a interface de inserção do FormView (clique para exibir a imagem em tamanho real)

Os detalhes do novo produto, Acme Coffee, são exibidos no FormView

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.