Partilhar via


Examinando os eventos associados à inserção, atualização e exclusão (C#)

por Scott Mitchell

Descarregar PDF

Neste tutorial, examinaremos o uso dos eventos que ocorrem antes, durante e depois de uma operação de inserção, atualização ou exclusão de um controle da Web de dados ASP.NET. Também veremos como personalizar a interface de edição para atualizar apenas um subconjunto dos campos do produto.

Introdução

Ao usar os recursos internos de inserção, edição ou exclusão dos controles GridView, DetailsView ou FormView, uma variedade de etapas ocorre quando o usuário final conclui o processo de adicionar um novo registro ou atualizar ou excluir um registro existente. Como discutimos no tutorial anterior, quando uma linha é editada no GridView, o botão Editar é substituído pelos botões Atualizar e Cancelar e os BoundFields se transformam em TextBoxes. Depois que o usuário final atualiza os dados e clica em Atualizar, as seguintes etapas são executadas no postback:

  1. O GridView preenche o seu ObjectDataSource's UpdateParameters com o(s) campo(s) de identificação exclusivo(s) do registro editado (através da propriedade DataKeyNames) juntamente com os valores introduzidos pelo utilizador.
  2. O GridView invoca seu método ObjectDataSource Update() , que por sua vez invoca o método apropriado no objeto subjacente (ProductsDAL.UpdateProduct, em nosso tutorial anterior)
  3. Os dados subjacentes, que agora incluem as alterações atualizadas, são repercutidos para o GridView

Durante essa sequência de etapas, vários eventos são acionados, permitindo que criemos manipuladores de eventos para adicionar lógica personalizada onde necessário. Por exemplo, antes da Etapa 1, o evento RowUpdating do GridView é acionado. Podemos, neste momento, cancelar a solicitação de atualização se houver algum erro de validação. Quando o Update() método é invocado, o evento Updating do ObjectDataSource é acionado, fornecendo uma oportunidade para adicionar ou personalizar os valores de qualquer um dos UpdateParameters. Depois de o método do objeto subjacente do ObjectDataSource ter concluído a execução, o evento Updated do ObjectDataSource é desencadeado. Um manipulador de eventos para o Updated evento pode inspecionar os detalhes sobre a operação de atualização, como quantas linhas foram afetadas e se ocorreu ou não uma exceção. Finalmente, após a Etapa 2, o evento do RowUpdated GridView é acionado, um manipulador de eventos para esse evento pode examinar informações adicionais sobre a operação de atualização que acabou de ser executada.

A Figura 1 mostra essa série de eventos e etapas ao atualizar um GridView. O padrão de evento na Figura 1 não é exclusivo da atualização com um GridView. Inserir, atualizar ou eliminar dados do GridView, DetailsView ou FormView gera a mesma sequência de eventos de pré e pós-nível tanto para o controlo Web de dados como para o ObjectDataSource.

Uma série de pré e pós-eventos são acionados ao atualizar dados em um GridView

Figura 1: Uma série de pré-eventos e pós-eventos são disparados ao atualizar dados num GridView (Clique para visualizar a imagem em tamanho real)

Neste tutorial, examinaremos o uso desses eventos para estender os recursos internos de inserção, atualização e exclusão dos controles da Web de dados ASP.NET. Também veremos como personalizar a interface de edição para atualizar apenas um subconjunto dos campos do produto.

Etapa 1: Atualizar os campos e um produto

Nas interfaces de edição do tutorial anterior, todos os campos do produto que não eram de apenas leitura tinham que ser incluídos. Se fôssemos remover um campo do GridView - digamos QuantityPerUnit - ao atualizar os dados, o controle Web de dados não definiria o valor de QuantityPerUnitUpdateParameters ObjectDataSource. O ObjectDataSource passaria um null valor para o método BLL (Business Logic Layer), que UpdateProduct alteraria a coluna do QuantityPerUnit registro de banco de dados editado para um NULL valor. Da mesma forma, se um campo obrigatório, como ProductName, for removido da interface de edição, a atualização falhará com uma exceção "Coluna 'ProductName' não permite nulos". O motivo para esse comportamento foi porque o ObjectDataSource foi configurado para chamar o ProductsBLL método da UpdateProduct classe, que esperava um parâmetro de entrada para cada um dos campos do produto. Portanto, a coleção do UpdateParameters ObjectDataSource continha um parâmetro para cada um dos parâmetros de entrada do método.

Se quisermos fornecer um controle da Web de dados que permita que o usuário final atualize apenas um subconjunto de campos, precisaremos definir programaticamente os valores ausentes UpdateParametersUpdating no manipulador de eventos do ObjectDataSource ou criar e chamar um método BLL que espera apenas um subconjunto dos campos. Vamos explorar esta última abordagem.

Especificamente, vamos criar uma página que exiba apenas os ProductName campos e UnitPrice em um GridView editável. A interface de edição deste GridView só permitirá que o usuário atualize os dois campos ProductName exibidos e UnitPrice. Como essa interface de edição fornece apenas um subconjunto dos campos de um produto, precisamos criar um ObjectDataSource que use o método BLL existente e tenha os valores de campo do produto ausentes UpdateProduct definidos programaticamente em seu Updating manipulador de eventos, ou precisamos criar um novo método BLL que espera apenas o subconjunto de campos definidos no GridView. Para este tutorial, vamos usar a última opção e criar uma sobrecarga do UpdateProduct método, que leva em apenas três parâmetros de entrada: productName, unitPrice, e productID:

[System.ComponentModel.DataObjectMethodAttribute
    (System.ComponentModel.DataObjectMethodType.Update, false)]
public bool UpdateProduct(string productName, decimal? unitPrice, int productID)
{
    Northwind.ProductsDataTable products = Adapter.GetProductByProductID(productID);
    if (products.Count == 0)
        // no matching record found, return false
        return false;

    Northwind.ProductsRow product = products[0];

    product.ProductName = productName;
    if (unitPrice == null) product.SetUnitPriceNull();
      else product.UnitPrice = unitPrice.Value;

    // Update the product record
    int rowsAffected = Adapter.Update(product);

    // Return true if precisely one row was updated, otherwise false
    return rowsAffected == 1;
}

Como o método original UpdateProduct , essa sobrecarga começa verificando se há um produto no banco de dados com o especificado ProductID. Caso contrário, ele retorna false, indicando que a solicitação para atualizar as informações do produto falhou. Caso contrário, ele atualiza os campos ProductName e UnitPrice do registro do produto existente de acordo e confirma a atualização chamando o método do TableAdapter Update(), passando na instância ProductsRow.

Com esta adição à nossa ProductsBLL classe, estamos prontos para criar a interface simplificada do GridView. Abra o DataModificationEvents.aspx na pasta EditInsertDelete e adicione um GridView à página. Crie um novo ObjectDataSource e configure-o para usar a classe ProductsBLL, com o seu mapeamento de método Select() para GetProducts e o seu mapeamento de método Update() para a sobrecarga UpdateProduct que recebe apenas os parâmetros de entrada productName, unitPrice e productID. A Figura 2 mostra o assistente de criação de fonte de dados (Create Data Source wizard) ao mapear a sobrecarga de método do ObjectDataSource para a nova sobrecarga de método da classe Update().

Mapeie o método Update() do ObjectDataSource com a nova versão sobrecarregada de UpdateProduct

Figura 2: Mapeie o método ObjectDataSource Update() para a nova UpdateProduct sobrecarga (Clique para visualizar a imagem em tamanho real)

Como nosso exemplo inicialmente precisará apenas da capacidade de editar dados, mas não de inserir ou excluir registros, Insert() reserve um momento para indicar explicitamente que os métodos Delete() do ObjectDataSource não devem ser mapeados para nenhuma classe da ProductsBLL, indo para as guias INSERT e DELETE e escolhendo (None) na lista suspensa.

Escolha (Nenhum) na lista de Drop-Down para as abas INSERT e DELETE

Figura 3: Escolha (Nenhum) da lista Drop-Down para as abas INSERIR e ELIMINAR (Clique para visualizar a imagem em tamanho real)

Depois de concluir o assistente, marque a caixa de seleção Ativar edição na tag inteligente do GridView.

Com a conclusão do assistente Criar fonte de dados e vinculá-lo ao GridView, o Visual Studio criou a sintaxe declarativa para ambos os controles. Vá para a visualização Source para inspecionar a marcação declarativa do ObjectDataSource, que é mostrada abaixo:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    OldValuesParameterFormatString="original_{0}" SelectMethod="GetProducts"
    TypeName="ProductsBLL" UpdateMethod="UpdateProduct">
    <UpdateParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="productID" Type="Int32" />
    </UpdateParameters>
</asp:ObjectDataSource>

Como não há mapeamentos para os métodos do ObjectDataSourceInsert() e Delete(), não há seções InsertParameters ou DeleteParameters. Além disso, como o método Update() é mapeado para a sobrecarga do método UpdateProduct que aceita apenas três parâmetros de entrada, a UpdateParameters secção tem apenas três instâncias Parameter.

Observe que a propriedade ObjectDataSource OldValuesParameterFormatString está definida como original_{0}. Essa propriedade é definida automaticamente pelo Visual Studio ao usar o assistente Configurar Fonte de Dados. No entanto, como nossos métodos BLL não esperam que o valor original ProductID seja passado, remova essa atribuição de propriedade completamente da sintaxe declarativa de ObjectDataSource.

Observação

Se você simplesmente limpar o OldValuesParameterFormatString valor da propriedade da janela Propriedades na visualização Design, a propriedade ainda existirá na sintaxe declarativa, mas será definida como uma cadeia de caracteres vazia. Remova completamente a propriedade da sintaxe declarativa ou, na janela Propriedades, defina o valor como padrão, {0}.

Enquanto o ObjectDataSource só tem UpdateParameters para o nome, preço e ID do produto, Visual Studio adicionou um BoundField ou CheckBoxField no GridView para cada um dos campos do produto.

O GridView contém um BoundField ou CheckBoxField para cada um dos campos do produto

Figura 4: O GridView contém um BoundField ou CheckBoxField para cada um dos campos do produto (Clique para visualizar a imagem em tamanho real)

Quando o usuário final edita um produto e clica em seu botão Atualizar, o GridView enumera os campos que não eram somente leitura. Em seguida, define o valor do parâmetro correspondente na coleção ObjectDataSource UpdateParameters para o valor inserido pelo usuário. Se não houver um parâmetro correspondente, o GridView adicionará um à coleção. Portanto, se nosso GridView contiver BoundFields e CheckBoxFields para todos os campos do produto, o ObjectDataSource acabará invocando a UpdateProduct sobrecarga que absorve todos esses parâmetros, apesar do fato de que a marcação declarativa do ObjectDataSource especifica apenas três parâmetros de entrada (consulte a Figura 5). Da mesma forma, se houver alguma combinação de campos de produto não somente leitura no GridView que não corresponda aos parâmetros de entrada para uma UpdateProduct sobrecarga, uma exceção será gerada ao tentar atualizar.

O GridView adicionará parâmetros à coleção UpdateParameters do ObjectDataSource

Figura 5: O GridView adicionará parâmetros à coleção do ObjectDataSource UpdateParameters (Clique para visualizar a imagem em tamanho real)

Para garantir que o ObjectDataSource invoque a UpdateProduct sobrecarga que aceita apenas o nome, o preço e a ID do produto, precisamos restringir o GridView a ter campos editáveis apenas para o ProductName e o UnitPrice. Isso pode ser feito removendo os outros BoundFields e CheckBoxFields, definindo a propriedade desses ReadOnly outros campos como true, ou por alguma combinação dos dois. Para este tutorial, vamos simplesmente remover todos os campos do GridView, exceto os ProductName e UnitPrice BoundFields, depois dos quais a marcação declarativa do GridView terá a seguinte aparência:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Columns>
        <asp:CommandField ShowEditButton="True" />
        <asp:BoundField DataField="ProductName"
          HeaderText="ProductName" SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
          SortExpression="UnitPrice" />
    </Columns>
</asp:GridView>

Embora a UpdateProduct sobrecarga espere três parâmetros de entrada, temos apenas dois BoundFields no nosso GridView. Isso ocorre porque o productID parâmetro de entrada é um valor de chave primária e é passado pelo valor da propriedade DataKeyNames para a linha editada.

O nosso GridView, juntamente com a UpdateProduct sobrecarga, permite a um utilizador editar apenas o nome e o preço de um produto sem perder nenhum dos outros campos do produto.

A interface permite editar apenas o nome e o preço do produto

Figura 6: A interface permite editar apenas o nome e o preço do produto (Clique para visualizar a imagem em tamanho real)

Observação

Conforme discutido no tutorial anterior, é de vital importância que o estado de exibição do GridView seja habilitado (o comportamento padrão). Se você definir a propriedade s EnableViewState de GridView como false, corre o risco de ter usuários simultâneos excluindo ou editando registros involuntariamente.

Melhorar aUnitPriceformatação

Embora o exemplo de GridView mostrado na Figura 6 funcione, o UnitPrice campo não é formatado, resultando em uma exibição de preço que não possui símbolos de moeda e tem quatro casas decimais. Para aplicar uma formatação de moeda às linhas não editáveis, basta definir a propriedade UnitPrice de BoundField para DataFormatString e sua propriedade {0:c} para HtmlEncode.

Defina as propriedades DataFormatString e HtmlEncode de UnitPrice de forma adequada

Figura 7: Definir as propriedades de UnitPriceDataFormatString e HtmlEncode de acordo (Clique para visualizar a imagem em tamanho real)

Com esta alteração, as linhas não editáveis formatam o preço como uma moeda; A linha editada, no entanto, ainda exibe o valor sem o símbolo de moeda e com quatro casas decimais.

Linhas não editáveis agora são formatadas como valores de moeda

Figura 8: Linhas não editáveis agora são formatadas como valores de moeda (Clique para visualizar a imagem em tamanho real)

As instruções de formatação especificadas na propriedade DataFormatString podem ser aplicadas à interface de edição ao definir a propriedade ApplyFormatInEditMode do BoundField como true (o padrão é false). Reserve um momento para definir esta propriedade como true.

Defina a propriedade ApplyFormatInEditMode de UnitPrice BoundField como true

Figura 9: Defina a propriedade BoundField UnitPrice como ApplyFormatInEditMode (true imagem em tamanho real)

Com esta alteração, o valor do UnitPrice exibido na linha editada também é formatado no formato de moeda.

Captura de tela do GridView mostrando o valor UnitPrice da linha editada formatado como uma moeda.

Figura 10: O valor da linha editada UnitPrice agora está formatado como uma moeda (Clique para visualizar a imagem em tamanho real)

No entanto, atualizar um produto com o símbolo da moeda na caixa de texto, como $19,00, gera um FormatException erro. Quando o GridView tenta atribuir os valores fornecidos pelo usuário à coleção do ObjectDataSource UpdateParameters , ele não consegue converter a UnitPrice cadeia de caracteres "$19.00" no decimal exigido pelo parâmetro (consulte a Figura 11). Para corrigir isso, podemos criar um manipulador de eventos para o evento do RowUpdating GridView e fazer com que ele analise o UnitPrice fornecido pelo usuário como um decimal formatado em moeda.

O evento GridView RowUpdating aceita como segundo parâmetro um objeto do tipo GridViewUpdateEventArgs, que inclui um NewValues dicionário como uma de suas propriedades que contém os valores fornecidos pelo usuário prontos para serem atribuídos à coleção do ObjectDataSource UpdateParameters . Podemos substituir o valor existente UnitPrice na coleção NewValues por um valor decimal analisado usando o formato de moeda com as seguintes linhas de código no manipulador de eventos RowUpdating:

protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
  if (e.NewValues["UnitPrice"] != null)
    e.NewValues["UnitPrice"] =
        decimal.Parse(e.NewValues["UnitPrice"].ToString(),
            System.Globalization.NumberStyles.Currency);
}

Se o usuário tiver fornecido um UnitPrice valor (como "$19.00"), esse valor será substituído pelo valor decimal calculado por Decimal.Parse, analisando o valor como uma moeda. Isso analisará corretamente o decimal no caso de quaisquer símbolos de moeda, vírgulas, pontos decimais e assim por diante, e usa a enumeração NumberStyles no namespace System.Globalization .

A Figura 11 mostra o problema causado por símbolos de moeda no fornecido pelo UnitPriceusuário, juntamente com como o manipulador de eventos do RowUpdating GridView pode ser utilizado para analisar corretamente essa entrada.

Diagrama mostrando como o ObjectDataSource processa o campo UnitPrice e como o manipulador de eventos RowUpdate do GridView converte uma cadeia de caracteres em decimal.

Figura 11: O valor da linha editada UnitPrice agora está formatado como uma moeda (Clique para visualizar a imagem em tamanho real)

Passo 2: ProibirNULL UnitPrices

Embora o banco de dados esteja configurado para permitir NULL valores na Products coluna da UnitPrice tabela, podemos querer impedir que os usuários que visitam essa página específica especifiquem um NULLUnitPrice valor. Ou seja, se um usuário não conseguir inserir um UnitPrice valor ao editar uma linha de produto, em vez de salvar os resultados no banco de dados, queremos exibir uma mensagem informando ao usuário que, através desta página, todos os produtos editados devem ter um preço especificado.

O GridViewUpdateEventArgs objeto passado para o manipulador de RowUpdating eventos do GridView contém uma Cancel propriedade que, se definida como true, encerra o processo de atualização. Vamos estender o RowUpdating manipulador de eventos para definir e.Cancel e true exibir uma mensagem explicando por que se o UnitPriceNewValues valor na coleção é null.

Comece adicionando um controle Label Web à página chamada MustProvideUnitPriceMessage. Esse controle Label será exibido se o usuário não especificar um UnitPrice valor ao atualizar um produto. Defina a propriedade do Text rótulo como "Você deve fornecer um preço para o produto". Também criei uma nova classe CSS com Styles.cssWarning a seguinte definição:

.Warning
{
    color: Red;
    font-style: italic;
    font-weight: bold;
    font-size: x-large;
}

Por fim, defina a propriedade Label CssClass como Warning. Neste ponto, o Designer deve mostrar a mensagem de aviso em um tamanho de fonte vermelho, negrito, itálico e extra grande acima do GridView, como mostra a Figura 12.

Um rótulo foi adicionado acima do GridView

Figura 12: Um rótulo foi adicionado acima do GridView (Clique para visualizar a imagem em tamanho real)

Por padrão, esse Label deve estar oculto, portanto, defina sua Visible propriedade como false no manipulador de Page_Load eventos:

protected void Page_Load(object sender, EventArgs e)
{
    MustProvideUnitPriceMessage.Visible = false;
}

Se o usuário tentar atualizar um produto sem especificar o UnitPrice, queremos cancelar a atualização e exibir o rótulo de aviso. Aumente o manipulador de eventos do RowUpdating GridView da seguinte maneira:

protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    if (e.NewValues["UnitPrice"] != null)
    {
        e.NewValues["UnitPrice"] =
            decimal.Parse(e.NewValues["UnitPrice"].ToString(),
                System.Globalization.NumberStyles.Currency);
    }
    else
    {
        // Show the Label
        MustProvideUnitPriceMessage.Visible = true;

        // Cancel the update
        e.Cancel = true;
    }
}

Se um usuário tentar salvar um produto sem especificar um preço, a atualização será cancelada e uma mensagem útil será exibida. Embora o banco de dados (e a lógica de negócios) permita NULLUnitPrice s, esta página de ASP.NET em particular não.

Um usuário não pode deixar UnitPrice em branco

Figura 13: Um usuário não pode deixar UnitPrice em branco (Clique para visualizar a imagem em tamanho real)

Até agora, vimos como usar o evento do RowUpdating GridView para alterar programaticamente os valores de parâmetro atribuídos à coleção do ObjectDataSource, UpdateParameters bem como cancelar o processo de atualização completamente. Esses conceitos são transferidos para os controles DetailsView e FormView e também se aplicam à inserção e exclusão.

Essas tarefas também podem ser feitas no nível ObjectDataSource por meio de manipuladores de eventos para seus Insertingeventos , Updatinge Deleting . Esses eventos são acionados antes que o método associado do objeto subjacente seja invocado e fornecem uma oportunidade de última chance para modificar a coleta de parâmetros de entrada ou cancelar a operação definitivamente. Os manipuladores de eventos para esses três eventos recebem um objeto do tipo ObjectDataSourceMethodEventArgs que tem duas propriedades de interesse:

  • Cancelar, que, se definido como true, cancela a operação que está sendo executada
  • InputParameters, que é a coleção de , InsertParametersou UpdateParameters, dependendo se o manipulador de DeleteParameterseventos é para o InsertingUpdating, ou Deleting evento

Para ilustrar o trabalho com os valores de parâmetro no nível ObjectDataSource, vamos incluir um DetailsView em nossa página que permite que os usuários adicionem um novo produto. Este DetailsView será usado para fornecer uma interface para adicionar rapidamente um novo produto ao banco de dados. Para manter uma interface de usuário consistente ao adicionar um novo produto, vamos permitir que o usuário insira apenas valores para os ProductName campos e UnitPrice . Por padrão, os valores que não são fornecidos na interface de inserção do DetailsView serão definidos como um NULL valor de banco de dados. No entanto, podemos usar o evento do Inserting ObjectDataSource para injetar diferentes valores padrão, como veremos em breve.

Etapa 3: Fornecendo uma interface para adicionar novos produtos

Arraste um DetailsView da Toolbox para o Designer acima do GridView, limpe suas Height propriedades e Width vincule-o ao ObjectDataSource já presente na página. Isso adicionará um BoundField ou CheckBoxField para cada um dos campos do produto. Como queremos usar este DetailsView para adicionar novos produtos, precisamos marcar a opção Ativar inserção na marca inteligente; no entanto, não há essa opção porque o método de Insert() ObjectDataSource não é mapeado para um método na ProductsBLL classe (lembre-se de que definimos esse mapeamento como (Nenhum) ao configurar a fonte de dados, consulte a Figura 3).

Para configurar o ObjectDataSource, selecione o link Configurar Fonte de Dados em sua marca inteligente, iniciando o assistente. A primeira tela permite alterar o objeto subjacente ao qual o ObjectDataSource está vinculado; deixe-o definido como ProductsBLL. A próxima tela lista os mapeamentos dos métodos do ObjectDataSource para o objeto subjacente. Embora tenhamos indicado explicitamente que Insert() e Delete() os métodos não devem ser mapeados para nenhum método, se acederes às abas INSERT e DELETE, verás que um mapeamento está lá. Isso ocorre porque os métodos de ProductsBLLAddProduct e DeleteProduct usam o atributo DataObjectMethodAttribute para indicar que são os métodos padrão para Insert() e Delete(), respectivamente. Assim, o assistente ObjectDataSource seleciona-os sempre que você executa o assistente, a menos que haja algum outro valor explicitamente especificado.

Deixe o Insert() método apontando para o AddProduct método, mas novamente defina a lista suspensa da guia DELETE como (Nenhum).

Defina a lista de Drop-Down da guia INSERT para o método AddProduct

Figura 14: Defina a lista de Drop-Down da guia INSERT para o método (Clique para visualizar a AddProductimagem em tamanho real)

Defina a lista de Drop-Down da guia DELETE como (Nenhuma)

Figura 15: Defina a lista de Drop-Down da guia DELETE como (Nenhum) (Clique para visualizar a imagem em tamanho normal)

Depois de fazer essas alterações, a sintaxe declarativa do ObjectDataSource será expandida para incluir uma InsertParameters coleção, conforme mostrado abaixo:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    SelectMethod="GetProducts" TypeName="ProductsBLL"
    UpdateMethod="UpdateProduct" OnUpdating="ObjectDataSource1_Updating"
    InsertMethod="AddProduct" OldValuesParameterFormatString="original_{0}">
    <UpdateParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <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>

Ao executar o assistente novamente, a propriedade OldValuesParameterFormatString foi adicionada de volta. Reserve um momento para limpar essa propriedade definindo-a com o valor padrão ({0}) ou removendo-a completamente da sintaxe declarativa.

Com o ObjectDataSource a fornecer capacidades de inserção, o smart tag do DetailsView agora incluirá a caixa de seleção Habilitar Inserção; volte ao Designer e marque esta opção. Em seguida, simplifique o DetailsView para que ele tenha apenas dois BoundFields - ProductName e UnitPrice - e o CommandField. Neste ponto, a sintaxe declarativa do DetailsView deve ter a seguinte aparência:

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Fields>
        <asp:BoundField DataField="ProductName"
          HeaderText="ProductName" SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
          SortExpression="UnitPrice" />
        <asp:CommandField ShowInsertButton="True" />
    </Fields>
</asp:DetailsView>

A Figura 16 mostra essa página quando visualizada através de um navegador neste momento. Como você pode ver, o DetailsView lista o nome e o preço do primeiro produto (Chai). O que queremos, no entanto, é uma interface de inserção que forneça um meio para o usuário adicionar rapidamente um novo produto ao banco de dados.

O DetailsView está a ser renderizado no modo Read-Only

Figura 16: O DetailsView está atualmente renderizado no modo Read-Only (Clique para visualizar a imagem em tamanho real)

Para mostrar o DetailsView em seu modo de inserção, precisamos definir a DefaultMode propriedade como Inserting. Isso renderiza o DetailsView no modo de inserção quando visitado pela primeira vez e o mantém lá depois de inserir um novo registro. Como mostra a Figura 17, esse DetailsView fornece uma interface rápida para adicionar um novo registro.

O DetailsView fornece uma interface para adicionar rapidamente um novo produto

Figura 17: O DetailsView fornece uma interface para adicionar rapidamente um novo produto (Clique para visualizar a imagem em tamanho real)

Quando o usuário insere um nome e preço de produto (como "Acme Water" e 1,99, como na Figura 17) e clica em Inserir, um postback ocorre e o fluxo de trabalho de inserção começa, culminando com um novo registro de produto sendo adicionado ao banco de dados. O DetailsView mantém sua interface de inserção e o GridView é automaticamente redirecionado para sua fonte de dados para incluir o novo produto, como mostra a Figura 18.

O Produto

Figura 18: O produto "Acme Water" foi adicionado ao banco de dados

Embora o GridView na Figura 18 não o mostre, os campos de produto ausentes da interface CategoryIDDetailsView, , SupplierIDQuantityPerUnit, e assim por diante recebem NULL valores de banco de dados. Você pode ver isso executando as seguintes etapas:

  1. Ir para o Gerenciador de Servidores no Visual Studio
  2. Expandindo o NORTHWND.MDF nó do banco de dados
  3. Clique com o botão direito do mouse no nó da Products tabela do banco de dados
  4. Selecione Mostrar dados da tabela

Isso listará todos os registros na Products tabela. Como mostra a Figura 19, todas as colunas do nosso novo produto, exceto ProductID, ProductName e UnitPrice, têm valores de NULL.

Os campos de produto não fornecidos no DetailsView são atribuídos valores NULL

Figura 19: Os campos de produto não fornecidos no DetailsView são valores atribuídos NULL (Clique para visualizar a imagem em tamanho real)

Podemos querer fornecer um valor padrão diferente de NULL um ou mais desses valores de coluna, seja porque NULL não é a melhor opção padrão ou porque a própria coluna do banco de dados não permite NULL s. Para fazer isso, podemos definir programaticamente os valores dos parâmetros da coleção DetailsView InputParameters . Essa atribuição pode ser feita no manipulador de eventos para o evento DetailsView ItemInserting ou no evento ObjectDataSource Inserting . Como já analisamos o uso dos eventos de pré e pós-nível no nível de controle da Web de dados, vamos explorar o uso dos eventos do ObjectDataSource desta vez.

Etapa 4: Atribuindo valores aosCategoryIDparâmetros eSupplierID

Para este tutorial, vamos imaginar que para a nossa aplicação ao adicionar um novo produto através desta interface deve ser atribuído um CategoryID e SupplierID valor de 1. Como mencionado anteriormente, o ObjectDataSource tem um par de eventos de pré e pós-nível que são acionados durante o processo de modificação de dados. Quando seu Insert() método é invocado, o ObjectDataSource primeiro gera seu Inserting evento, em seguida, chama o método para o qual seu Insert() método foi mapeado e, finalmente, gera o Inserted evento. O Inserting manipulador de eventos nos oferece uma última oportunidade de ajustar os parâmetros de entrada ou cancelar a operação definitivamente.

Observação

Em um aplicativo do mundo real, você provavelmente gostaria de permitir que o usuário especificasse a categoria e o fornecedor ou escolheria esse valor para eles com base em alguns critérios ou lógica de negócios (em vez de selecionar cegamente um ID de 1). Independentemente disso, o exemplo ilustra como definir programaticamente o valor de um parâmetro de entrada do evento de pré-nível do ObjectDataSource.

Reserve um momento para criar um manipulador de eventos para o evento do Inserting ObjectDataSource. Observe que o segundo parâmetro de entrada do manipulador de eventos é um objeto do tipo ObjectDataSourceMethodEventArgs, que tem uma propriedade para acessar a coleção de parâmetros (InputParameters) e uma propriedade para cancelar a operação (Cancel).

protected void ObjectDataSource1_Inserting
    (object sender, ObjectDataSourceMethodEventArgs e)
{

}

Neste ponto, a InputParameters propriedade contém a coleção InsertParameters do ObjectDataSource com os valores atribuídos provenientes de DetailsView. Para alterar o valor de um destes parâmetros, basta usar: e.InputParameters["paramName"] = value. Portanto, para definir os valores de CategoryID e SupplierID para 1, ajuste o manipulador de eventos Inserting para ter a seguinte aparência:

protected void ObjectDataSource1_Inserting
    (object sender, ObjectDataSourceMethodEventArgs e)
{
    e.InputParameters["CategoryID"] = 1;
    e.InputParameters["SupplierID"] = 1;
}

Desta vez, ao adicionar um novo produto (como Acme Soda), as CategoryID colunas e SupplierID do novo produto são definidas como 1 (veja a Figura 20).

Novos produtos agora têm seus valores CategoryID e SupplierID definidos como 1

Figura 20: Novos produtos agora têm seus CategoryID e SupplierID valores definidos como 1 (Clique para visualizar a imagem em tamanho real)

Resumo

Durante o processo de edição, inserção e exclusão, o controlo de dados da Web e o ObjectDataSource passam por vários pré-eventos e pós-eventos. Neste tutorial, examinamos os eventos de pré-nível e vimos como usá-los para personalizar os parâmetros de entrada ou cancelar completamente a operação de modificação de dados, tanto do controle da Web de dados quanto dos eventos do ObjectDataSource. No próximo tutorial, veremos como criar e usar manipuladores de eventos para os eventos de pós-nível.

Feliz Programação!

Sobre o Autor

Scott Mitchell, autor de sete livros sobre ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias Web da Microsoft desde 1998. Scott trabalha como consultor, formador e escritor independente. Seu último livro é Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Ele pode ser contatado em mitchell@4GuysFromRolla.com.

Um agradecimento especial a

Esta série de tutoriais foi revisada por muitos revisores úteis. Os principais revisores para este tutorial foram Jackie Goor e Liz Shulok. Interessado em rever meus próximos artigos do MSDN? Se for o caso, envie-me uma mensagem para mitchell@4GuysFromRolla.com.