Adicionar confirmação do lado do cliente ao excluir (VB)

por Scott Mitchell

Baixar PDF

Nas interfaces que criamos até agora, um usuário pode excluir dados acidentalmente clicando no botão Excluir quando quiser clicar no botão Editar. Neste tutorial, adicionaremos uma caixa de diálogo de confirmação do lado do cliente que aparece quando o botão Excluir é clicado.

Introdução

Nos últimos tutoriais, vimos como usar nossa arquitetura de aplicativo, ObjectDataSource e os controles da Web de dados em conjunto para fornecer recursos de inserção, edição e exclusão. As interfaces de exclusão que examinamos até agora foram compostas por um botão Excluir que, quando clicado, causa um postback e invoca o método ObjectDataSource.Delete() Em Delete() seguida, o método invoca o método configurado da Camada de Lógica de Negócios, que propaga a chamada para a Camada de Acesso a Dados, emitindo a instrução real DELETE para o banco de dados.

Embora essa interface do usuário permita que os visitantes excluam registros por meio dos controles GridView, DetailsView ou FormView, ela não tem qualquer tipo de confirmação quando o usuário clica no botão Excluir. Se um usuário clicar acidentalmente no botão Excluir quando quiser clicar em Editar, o registro que ele pretendia atualizar será excluído. Para ajudar a evitar isso, neste tutorial, adicionaremos uma caixa de diálogo de confirmação do lado do cliente que aparece quando o botão Excluir é clicado.

A função JavaScript confirm(string) exibe seu parâmetro de entrada de cadeia de caracteres como o texto dentro de uma caixa de diálogo modal que vem equipada com dois botões – OK e Cancelar (consulte a Figura 1). A confirm(string) função retorna um valor booliano dependendo de qual botão é clicado (true, se o usuário clicar em OK e false se clicar em Cancelar).

O método Confirm(string) do JavaScript exibe uma caixa de mensagem modal Client-Side

Figura 1: o método JavaScript confirm(string) exibe uma caixa de mensagem modal Client-Side

Durante um envio de formulário, se um valor de false for retornado de um manipulador de eventos do lado do cliente, o envio do formulário será cancelado. Usando esse recurso, podemos fazer com que o manipulador de eventos do lado onclick do cliente do botão Excluir retorne o valor de uma chamada para confirm("Are you sure you want to delete this product?"). Se o usuário clicar em Cancelar, confirm(string) retornará false, fazendo com que o envio do formulário seja cancelado. Sem postback, o produto cujo botão Excluir foi clicado não será excluído. No entanto, se o usuário clicar em OK na caixa de diálogo de confirmação, o postback continuará inabalável e o produto será excluído. Consulte Usando o método javaScript para confirm() controlar o envio de formulário para obter mais informações sobre essa técnica.

Adicionar o script do lado do cliente necessário difere ligeiramente se estiver usando modelos do que ao usar um CommandField. Portanto, neste tutorial, examinaremos um exemplo de FormView e GridView.

Observação

O uso de técnicas de confirmação do lado do cliente, como as discutidas neste tutorial, pressupõe que os usuários estejam visitando com navegadores que dão suporte a JavaScript e que tenham o JavaScript habilitado. Se qualquer uma dessas suposições não for verdadeira para um usuário específico, clicar no botão Excluir causará imediatamente um postback (não exibir uma caixa de mensagem de confirmação).

Etapa 1: Criando um FormView que dá suporte à exclusão

Comece adicionando um FormView à ConfirmationOnDelete.aspx página na pasta , associando-o EditInsertDelete a um novo ObjectDataSource que efetua pull das informações do produto por meio do ProductsBLL método da classe s GetProducts() . Configure também o ObjectDataSource para que o ProductsBLL método da classe s DeleteProduct(productID) seja mapeado para o método objectDataSource; Delete() verifique se as listas suspensas das guias INSERT e UPDATE estão definidas como (Nenhum). Por fim, marcar caixa de seleção Habilitar Paginação na marca inteligente formView.

Após essas etapas, a nova marcação declarativa do ObjectDataSource será semelhante à seguinte:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    DeleteMethod="DeleteProduct" OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProducts" TypeName="ProductsBLL">
    <DeleteParameters>
        <asp:Parameter Name="productID" Type="Int32" />
    </DeleteParameters>
</asp:ObjectDataSource>

Como em nossos exemplos anteriores que não usavam simultaneidade otimista, reserve um momento para limpar a propriedade objectDataSource.OldValuesParameterFormatString

Como ele foi associado a um controle ObjectDataSource que dá suporte apenas à exclusão, o FormView s ItemTemplate oferece apenas o botão Excluir, sem os botões Novo e Atualizar. No entanto, a marcação declarativa do FormView inclui um supérfluo e InsertItemTemplate, que podem ser removidosEditItemTemplate. Reserve um momento para personalizar o ItemTemplate para que seja mostrado apenas um subconjunto dos campos de dados do produto. Configurei o meu para mostrar o nome do produto em um <h3> título acima de seu fornecedor e nomes de categoria (juntamente com o botão Excluir).

<asp:FormView ID="FormView1" AllowPaging="True" DataKeyNames="ProductID"
    DataSourceID="ObjectDataSource1" runat="server">
    <ItemTemplate>
        <h3><i><%# Eval("ProductName") %></i></h3>
        <b>Category:</b>
        <asp:Label ID="CategoryNameLabel" runat="server"
            Text='<%# Eval("CategoryName") %>'>
        </asp:Label><br />
        <b>Supplier:</b>
        <asp:Label ID="SupplierNameLabel" runat="server"
            Text='<%# Eval("SupplierName") %>'>
        </asp:Label><br />
        <asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
            CommandName="Delete" Text="Delete">
        </asp:LinkButton>
    </ItemTemplate>
</asp:FormView>

Com essas alterações, temos uma página da Web totalmente funcional que permite que um usuário alterne os produtos um de cada vez, com a capacidade de excluir um produto simplesmente clicando no botão Excluir. A Figura 2 mostra uma captura de tela do nosso progresso até agora quando exibida por meio de um navegador.

O FormView mostra informações sobre um único produto

Figura 2: O FormView mostra informações sobre um único produto (clique para exibir a imagem em tamanho real)

Etapa 2: Chamando a função confirm(string) do evento Delete Buttons Client-Side onclick

Com o FormView criado, a etapa final é configurar o botão Excluir de modo que, quando ele é clicado pelo visitante, a função JavaScript confirm(string) é invocada. A adição de script do lado do cliente a um evento do lado onclick do cliente Button, LinkButton ou ImageButton pode ser realizada por meio do uso do OnClientClick property, que é novo no ASP.NET 2.0. Como queremos que o valor da confirm(string) função seja retornado, basta definir essa propriedade como: return confirm('Are you certain that you want to delete this product?');

Após essa alteração, a sintaxe declarativa Excluir LinkButton deverá ser semelhante a:

<asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
    CommandName="Delete" Text="Delete"
    OnClientClick="return confirm('Are you certain you want to delete this product?');">
</asp:LinkButton>

Isso é tudo o que há para ele! A Figura 3 mostra uma captura de tela dessa confirmação em ação. Clicar no botão Excluir abre a caixa de diálogo confirmar. Se o usuário clicar em Cancelar, o postback será cancelado e o produto não será excluído. Se, no entanto, o usuário clicar em OK, o postback continuará e o método objectDataSource será Delete() invocado, culminando na exclusão do registro de banco de dados.

Observação

A cadeia de caracteres passada para a confirm(string) função JavaScript é delimitada com apóstrofos (em vez de aspas). No JavaScript, as cadeias de caracteres podem ser delimitadas usando qualquer um dos caracteres. Usamos apóstrofos aqui para que os delimitadores para a cadeia de caracteres passada confirm(string) não introduzam uma ambiguidade com os delimitadores usados para o valor da OnClientClick propriedade.

Uma confirmação agora é exibida ao clicar no botão Excluir

Figura 3: Uma confirmação agora é exibida ao clicar no botão Excluir (clique para exibir a imagem em tamanho real)

Etapa 3: Configurando a propriedade OnClientClick para o botão Excluir em um CommandField

Ao trabalhar com um Button, LinkButton ou ImageButton diretamente em um modelo, uma caixa de diálogo de confirmação pode ser associada a ela simplesmente configurando sua OnClientClick propriedade para retornar os resultados da função JavaScript confirm(string) . No entanto, o CommandField - que adiciona um campo de botões Excluir a um GridView ou DetailsView - não tem uma OnClientClick propriedade que pode ser definida declarativamente. Em vez disso, devemos referenciar programaticamente o botão Excluir no manipulador de eventos apropriado DataBound de GridView ou DetailsView e, em seguida, definir sua OnClientClick propriedade lá.

Observação

Ao definir a propriedade do botão Excluir no OnClientClick manipulador de eventos apropriado DataBound , temos acesso aos dados associados ao registro atual. Isso significa que podemos estender a mensagem de confirmação para incluir detalhes sobre o registro específico, como" Tem certeza de que deseja excluir o produto Chai?" Essa personalização também é possível em modelos usando a sintaxe de associação de dados.

Para praticar a configuração da OnClientClick propriedade para os botões Excluir em um CommandField, vamos adicionar um GridView à página. Configure este GridView para usar o mesmo controle ObjectDataSource que o FormView usa. Limite também os BoundFields do GridView para incluir apenas o nome, a categoria e o fornecedor do produto. Por fim, marcar a caixa de seleção Habilitar Exclusão da marca inteligente GridView. Isso adicionará um CommandField à coleção gridView com Columns sua ShowDeleteButton propriedade definida truecomo .

Depois de fazer essas alterações, a marcação declarativa do GridView deve ser semelhante à seguinte:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" />
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category" ReadOnly="True"
            SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName" HeaderText="Supplier" ReadOnly="True"
            SortExpression="SupplierName" />
    </Columns>
</asp:GridView>

O CommandField contém uma única instância delete LinkButton que pode ser acessada programaticamente no manipulador de eventos gridView.RowDataBound Depois de referenciados, podemos definir sua OnClientClick propriedade adequadamente. Crie um manipulador de eventos para o RowDataBound evento usando o seguinte código:

Protected Sub GridView1_RowDataBound(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
    Handles GridView1.RowDataBound

    If e.Row.RowType = DataControlRowType.DataRow Then
        ' reference the Delete LinkButton
        Dim db As LinkButton = CType(e.Row.Cells(0).Controls(0), LinkButton)

        ' Get information about the product bound to the row
        Dim product As Northwind.ProductsRow = _
            CType(CType(e.Row.DataItem, System.Data.DataRowView).Row, _
            Northwind.ProductsRow)

        db.OnClientClick = String.Format( _
            "return confirm('Are you certain you want to delete the {0} product?');", _
            product.ProductName.Replace("'", "\'"))
    End If
End Sub

Esse manipulador de eventos funciona com linhas de dados (aquelas que terão o botão Excluir) e começa referenciando programaticamente o botão Excluir. Em geral, use o seguinte padrão:

Dim obj As ButtonType = _
    CType(e.Row.Cells(commandFieldIndex).Controls(controlIndex), ButtonType)

ButtonType é o tipo de botão que está sendo usado pelo CommandField - Button, LinkButton ou ImageButton. Por padrão, o CommandField usa LinkButtons, mas isso pode ser personalizado por meio do CommandField s ButtonType property. O commandFieldIndex é o índice ordinal do CommandField dentro da coleção GridView, Columns enquanto controlIndex é o índice do botão Delete dentro da coleção CommandField s Controls . O valor controlIndex depende da posição do botão em relação a outros botões no CommandField. Por exemplo, se o único botão exibido no CommandField for o botão Excluir, use um índice de 0. Se, no entanto, houver um botão Editar que precede o botão Excluir, use um índice de 2. O motivo pelo qual um índice de 2 é usado é porque dois controles são adicionados pelo CommandField antes do botão Excluir: o botão Editar e um LiteralControl que é usado para adicionar algum espaço entre os botões Editar e Excluir.

Para nosso exemplo específico, o CommandField usa LinkButtons e, sendo o campo mais à esquerda, tem um commandFieldIndex de 0. Como não há outros botões além do botão Excluir no CommandField, usamos um controlIndex de 0.

Depois de referenciar o botão Excluir no CommandField, em seguida, obteremos informações sobre o produto associado à linha GridView atual. Por fim, definimos a propriedade do botão Excluir como OnClientClick o JavaScript apropriado, que inclui o nome do produto. Como a cadeia de caracteres JavaScript passada para a confirm(string) função é delimitada usando apóstrofos, devemos escapar de todos os apóstrofos que aparecem dentro do nome do produto. Em particular, todos os apóstrofos no nome do produto são escapados com "\'".

Com essas alterações concluídas, clicar em um botão Excluir no GridView exibe uma caixa de diálogo de confirmação personalizada (consulte a Figura 4). Assim como acontece com a caixa de mensagem de confirmação do FormView, se o usuário clicar em Cancelar, o postback será cancelado, impedindo assim que a exclusão ocorra.

Observação

Essa técnica também pode ser usada para acessar programaticamente o botão Excluir no CommandField em um DetailsView. No entanto, para o DetailsView, você criaria um manipulador de eventos para o DataBound evento, pois o DetailsView não tem um RowDataBound evento.

Clicar no botão Excluir gridView exibe uma caixa de diálogo de confirmação personalizada

Figura 4: Clicar no botão Excluir do GridView exibe uma caixa de diálogo de confirmação personalizada (clique para exibir a imagem em tamanho real)

Usando TemplateFields

Uma das desvantagens do CommandField é que seus botões devem ser acessados por meio da indexação e que o objeto resultante deve ser convertido no tipo de botão apropriado (Button, LinkButton ou ImageButton). O uso de "números mágicos" e tipos embutidos em código convida problemas que não podem ser descobertos até o runtime. Por exemplo, se você ou outro desenvolvedor adicionar novos botões ao CommandField em algum momento no futuro (como um botão Editar) ou alterar a ButtonType propriedade, o código existente ainda será compilado sem erros, mas visitar a página pode causar uma exceção ou um comportamento inesperado, dependendo de como o código foi escrito e quais alterações foram feitas.

Uma abordagem alternativa é converter os CommandFields de GridView e DetailsView em TemplateFields. Isso gerará um TemplateField com um ItemTemplate que tem um LinkButton (ou Button ou ImageButton) para cada botão no CommandField. Essas propriedades de botões podem ser atribuídas OnClientClick declarativamente, como vimos com o FormView, ou podem ser acessadas programaticamente no manipulador de eventos apropriado DataBound usando o seguinte padrão:

Dim obj As ButtonType = CType(e.Row.FindControl("controlID"), ButtonType)

Em que controlID é o valor da propriedade s do ID botão. Embora esse padrão ainda exija um tipo embutido em código para a conversão, ele remove a necessidade de indexação, permitindo que o layout seja alterado sem resultar em um erro de runtime.

Resumo

A função JavaScript confirm(string) é uma técnica comumente usada para controlar o fluxo de trabalho de envio de formulário. Quando executada, a função exibe uma caixa de diálogo modal do lado do cliente que inclui dois botões, OK e Cancelar. Se o usuário clicar em OK, a confirm(string) função retornará true; clicar em Cancelar retornará false. Essa funcionalidade, juntamente com o comportamento de um navegador para cancelar um envio de formulário se um manipulador de eventos durante o processo de envio retornar false, poderá ser usada para exibir uma caixa de mensagens de confirmação ao excluir um registro.

A confirm(string) função pode ser associada a um manipulador de eventos do lado onclick do cliente do controle Web de botão por meio da propriedade s do OnClientClick controle. Ao trabalhar com um botão Excluir em um modelo - em um dos modelos do FormView ou em um TemplateField no DetailsView ou GridView - essa propriedade pode ser definida de forma declarativa ou programática, como vimos neste tutorial.

Programação feliz!

Sobre o autor

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