Personalizar a interface de edição do DataList (C#)

por Scott Mitchell

Baixar PDF

Neste tutorial, criaremos uma interface de edição mais avançada para DataList, uma que inclui DropDownLists e uma CheckBox.

Introdução

A marcação e os controles da Web nos DataLists EditItemTemplate definem sua interface editável. Em todos os exemplos editáveis de DataList que examinamos até agora, a interface editável foi composta por controles da Web TextBox. No tutorial anterior , melhoramos a experiência do usuário em tempo de edição adicionando controles de validação.

O EditItemTemplate pode ser expandido ainda mais para incluir controles da Web diferentes do TextBox, como DropDownLists, RadioButtonLists, Calendars e assim por diante. Assim como acontece com TextBoxes, ao personalizar a interface de edição para incluir outros controles da Web, empregue as seguintes etapas:

  1. Adicione o controle da Web ao EditItemTemplate.
  2. Use a sintaxe de associação de dados para atribuir o valor do campo de dados correspondente à propriedade apropriada.
  3. UpdateCommand No manipulador de eventos, acesse programaticamente o valor de controle da Web e passe-o para o método BLL apropriado.

Neste tutorial, criaremos uma interface de edição mais avançada para DataList, uma que inclui DropDownLists e uma CheckBox. Em particular, criaremos uma DataList que lista as informações do produto e permite que o nome, o fornecedor, a categoria e os status descontinuados do produto sejam atualizados (consulte a Figura 1).

A interface de edição inclui uma TextBox, duas DropDownLists e uma CheckBox

Figura 1: a interface de edição inclui uma TextBox, duas DropDownLists e uma CheckBox (clique para exibir a imagem em tamanho real)

Etapa 1: Exibindo informações do produto

Antes de podermos criar a interface editável do DataList, primeiro precisamos criar a interface somente leitura. Comece abrindo a CustomizedUI.aspx página da EditDeleteDataList pasta e, no Designer, adicione um DataList à página, definindo sua ID propriedade como Products. Na marca inteligente DataList, crie um novo ObjectDataSource. Nomeie esse novo ObjectDataSource ProductsDataSource e configure-o para recuperar dados do método s da ProductsBLLGetProducts classe. Assim como nos tutoriais anteriores editáveis do DataList, atualizaremos as informações do produto editado acessando diretamente a Camada de Lógica de Negócios. Assim, defina as listas suspensas nas guias UPDATE, INSERT e DELETE como (Nenhum).

Defina as guias UPDATE, INSERT e DELETE Drop-Down Listas como (Nenhum)

Figura 2: Definir as guias UPDATE, INSERT e DELETE Drop-Down Listas como (Nenhum) (Clique para exibir a imagem em tamanho real)

Depois de configurar o ObjectDataSource, o Visual Studio criará um padrão ItemTemplate para DataList que lista o nome e o valor de cada um dos campos de dados retornados. Modifique o ItemTemplate para que o modelo liste o nome do produto em um <h4> elemento juntamente com o nome da categoria, o nome do fornecedor, o preço e os status descontinuados. Além disso, adicione um botão Editar, certificando-se de que sua CommandName propriedade esteja definida como Editar. A marcação declarativa para a seguinte ItemTemplate :

<ItemTemplate>
    <h4>
        <asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>' />
    </h4>
    <table border="0">
        <tr>
            <td class="ProductPropertyLabel">Category:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="CategoryNameLabel" runat="server"
                    Text='<%# Eval("CategoryName") %>' />
            </td>
            <td class="ProductPropertyLabel">Supplier:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="SupplierNameLabel" runat="server"
                    Text='<%# Eval("SupplierName") %>' />
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Discontinued:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="DiscontinuedLabel" runat="server"
                    Text='<%# Eval("Discontinued") %>' />
            </td>
            <td class="ProductPropertyLabel">Price:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="UnitPriceLabel" runat="server"
                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
            </td>
        </tr>
        <tr>
            <td colspan="4">
                <asp:Button runat="Server" ID="EditButton"
                    Text="Edit" CommandName="Edit" />
            </td>
        </tr>
    </table>
    <br />
</ItemTemplate>

A marcação acima dispõe as informações do produto usando um <título h4> para o nome do produto e uma de quatro colunas <table> para os campos restantes. As ProductPropertyLabel classes e ProductPropertyValue CSS, definidas em Styles.css, foram discutidas em tutoriais anteriores. A Figura 3 mostra nosso progresso quando exibido por meio de um navegador.

O nome, o fornecedor, a categoria, o status descontinuado e o preço de cada produto são exibidos

Figura 3: o nome, o fornecedor, a categoria, o status descontinuado e o preço de cada produto são exibidos (clique para exibir a imagem em tamanho real)

Etapa 2: Adicionar os controles da Web à interface de edição

A primeira etapa na criação da interface de edição datalist personalizada é adicionar os controles da Web necessários ao EditItemTemplate. Em particular, precisamos de um DropDownList para a categoria, outro para o fornecedor e uma CheckBox para o estado descontinuado. Como o preço do produto não é editável neste exemplo, podemos continuar exibindo-o usando um controle Web label.

Para personalizar a interface de edição, clique no link Editar Modelos da marca inteligente DataList e escolha a opção EditItemTemplate na lista suspensa. Adicione um DropDownList ao EditItemTemplate e defina como IDCategories.

Adicionar um DropDownList para as Categorias

Figura 4: Adicionar um DropDownList para as Categorias (Clique para exibir a imagem em tamanho real)

Em seguida, na marca inteligente DropDownList, selecione a opção Escolher Fonte de Dados e crie um novo ObjectDataSource chamado CategoriesDataSource. Configure este ObjectDataSource para usar o CategoriesBLL método da classe s GetCategories() (consulte a Figura 5). Em seguida, o Assistente de Configuração da Fonte de Dados dropDownList solicita que os campos de dados sejam usados para cada ListItem s Text e Value propriedades. Fazer com que o DropDownList exiba o CategoryName campo de dados e use o CategoryID como o valor, conforme mostrado na Figura 6.

Criar um novo objetoDataSource chamado CategoriesDataSource

Figura 5: Criar um novo objetoDataSource nomeado CategoriesDataSource (clique para exibir a imagem em tamanho real)

Configurar os campos de exibição e valor do DropDownList

Figura 6: Configurar os campos exibição e valor do DropDownList (clique para exibir a imagem em tamanho real)

Repita esta série de etapas para criar um DropDownList para os fornecedores. Defina o ID para este DropDownList como Suppliers e nomeie seu ObjectDataSource SuppliersDataSource.

Depois de adicionar as duas DropDownLists, adicione uma CheckBox para o estado descontinuado e uma TextBox para o nome do produto. Defina os ID s para CheckBox e TextBox como Discontinued e ProductName, respectivamente. Adicione um RequiredFieldValidator para garantir que o usuário forneça um valor para o nome do produto.

Por fim, adicione os botões Atualizar e Cancelar. Lembre-se de que, para esses dois botões, é imperativo que suas CommandName propriedades sejam definidas como Atualizar e Cancelar, respectivamente.

Fique à vontade para definir a interface de edição como desejar. Optei por usar o mesmo layout de quatro colunas <table> da interface somente leitura, como ilustra a sintaxe declarativa e a captura de tela a seguir:

<EditItemTemplate>
    <h4>
        <asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>' />
    </h4>
    <table border="0">
        <tr>
            <td class="ProductPropertyLabel">Name:</td>
            <td colspan="3" class="ProductPropertyValue">
                <asp:TextBox runat="server" ID="ProductName" Width="90%" />
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1"
                    ControlToValidate="ProductName"
                    ErrorMessage="You must enter a name for the product."
                    runat="server">*</asp:RequiredFieldValidator>
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Category:</td>
            <td class="ProductPropertyValue">
                <asp:DropDownList ID="Categories" runat="server"
                    DataSourceID="CategoriesDataSource"
                    DataTextField="CategoryName" DataValueField="CategoryID" />
            </td>
            <td class="ProductPropertyLabel">Supplier:</td>
            <td class="ProductPropertyValue">
                <asp:DropDownList ID="Suppliers" DataTextField="CompanyName"
                    DataSourceID="SuppliersDataSource"
                    DataValueField="SupplierID" runat="server" />
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Discontinued:</td>
            <td class="ProductPropertyValue">
                <asp:CheckBox runat="server" id="Discontinued" />
            </td>
            <td class="ProductPropertyLabel">Price:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="UnitPriceLabel" runat="server"
                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
            </td>
        </tr>
        <tr>
            <td colspan="4">
                <asp:Button runat="Server" ID="UpdateButton" CommandName="Update"
                    Text="Update" />
                 
                <asp:Button runat="Server" ID="CancelButton" CommandName="Cancel"
                    Text="Cancel" CausesValidation="False" />
            </td>
        </tr>
    </table>
    <br />
    <asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
        OldValuesParameterFormatString="original_{0}" SelectMethod="GetCategories"
        TypeName="CategoriesBLL">
    </asp:ObjectDataSource>
    <asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
        OldValuesParameterFormatString="original_{0}" SelectMethod="GetSuppliers"
        TypeName="SuppliersBLL">
    </asp:ObjectDataSource>
</EditItemTemplate>

A interface de edição é definida como a interface Read-Only

Figura 7: a interface de edição é disposta como a interface de Read-Only (clique para exibir a imagem em tamanho real)

Etapa 3: Criando os manipuladores de eventos EditCommand e CancelCommand

Atualmente, não há sintaxe de associação de dados no EditItemTemplate (exceto para o UnitPriceLabel, que foi copiado textualmente do ItemTemplate). Adicionaremos a sintaxe de vinculação de dados momentaneamente, mas primeiro vamos criar os manipuladores de eventos para os eventos e CancelCommand DataListEditCommand. Lembre-se de que a responsabilidade do manipulador de EditCommand eventos é renderizar a interface de edição para o item DataList cujo botão Editar foi clicado, enquanto o CancelCommand trabalho do s é retornar a DataList para seu estado de pré-edição.

Crie esses dois manipuladores de eventos e use o seguinte código:

protected void Products_EditCommand(object source, DataListCommandEventArgs e)
{
    // Set the DataList's EditItemIndex property and rebind the data
    Products.EditItemIndex = e.Item.ItemIndex;
    Products.DataBind();
}
protected void Products_CancelCommand(object source, DataListCommandEventArgs e)
{
    // Return to DataList to its pre-editing state
    Products.EditItemIndex = -1;
    Products.DataBind();
}

Com esses dois manipuladores de eventos em vigor, clicar no botão Editar exibe a interface de edição e clicar no botão Cancelar retorna o item editado para seu modo somente leitura. A Figura 8 mostra o DataList depois que o botão Editar é clicado para o Gumbo Mix do Chef Anton. Como ainda não adicionamos nenhuma sintaxe de associação de dados à interface de edição, a ProductName TextBox está em branco, a Discontinued Caixa de Seleção desmarcada e os primeiros itens selecionados nas Categories listas e Suppliers DropDownLists.

Captura de tela mostrando o EditItemTemplate datalist depois que os manipuladores de eventos EditCommand e CancelCommand foram adicionados e o botão Editar foi selecionado.

Figura 8: Clicar no botão Editar exibe a interface de edição (clique para exibir a imagem em tamanho real)

Etapa 4: adicionando a sintaxe DataBinding à interface de edição

Para que a interface de edição exiba os valores atuais do produto, precisamos usar a sintaxe de associação de dados para atribuir os valores de campo de dados aos valores de controle da Web apropriados. A sintaxe de vinculação de dados pode ser aplicada por meio do Designer acessando a tela Editar Modelos e selecionando o link Editar DataBindings nas marcas inteligentes de controles da Web. Como alternativa, a sintaxe de vinculação de dados pode ser adicionada diretamente à marcação declarativa.

Atribua o valor do ProductName campo de dados à ProductName propriedade TextBox s Text , aos CategoryID valores do campo de dados e SupplierID às Categories propriedades e Suppliers DropDownLists SelectedValue e o valor do Discontinued campo de dados à Discontinued propriedade s Checked CheckBox. Depois de fazer essas alterações, por meio do Designer ou diretamente por meio da marcação declarativa, reveja a página por meio de um navegador e clique no botão Editar para o Gumbo Mix do Chef Anton. Como mostra a Figura 9, a sintaxe de associação de dados adicionou os valores atuais ao TextBox, DropDownLists e CheckBox.

Captura de tela mostrando o EditItemTemplate datalist depois que a sintaxe DataBinding foi adicionada e o botão Editar foi selecionado.

Figura 9: Clicar no botão Editar exibe a interface de edição (clique para exibir a imagem em tamanho real)

Etapa 5: salvar as alterações do usuário no manipulador de eventos UpdateCommand

Quando o usuário edita um produto e clica no botão Atualizar, ocorre um postback e o evento DataList é UpdateCommand acionado. No manipulador de eventos, precisamos ler os valores dos controles da Web na EditItemTemplate interface e com a BLL para atualizar o produto no banco de dados. Como vimos nos tutoriais anteriores, o ProductID do produto atualizado é acessível por meio da DataKeys coleção. Os campos inseridos pelo usuário são acessados referenciando programaticamente os controles da Web usando FindControl("controlID"), como mostra o seguinte código:

protected void Products_UpdateCommand(object source, DataListCommandEventArgs e)
{
    // Make sure the page is valid...
    if (!Page.IsValid)
        return;
    // Read in the ProductID from the DataKeys collection
    int productID = Convert.ToInt32(Products.DataKeys[e.Item.ItemIndex]);
    // Read in the product name and price values
    TextBox productName = (TextBox)e.Item.FindControl("ProductName");
    DropDownList categories = (DropDownList)e.Item.FindControl("Categories");
    DropDownList suppliers = (DropDownList)e.Item.FindControl("Suppliers");
    CheckBox discontinued = (CheckBox)e.Item.FindControl("Discontinued");
    string productNameValue = null;
    if (productName.Text.Trim().Length > 0)
        productNameValue = productName.Text.Trim();
    int categoryIDValue = Convert.ToInt32(categories.SelectedValue);
    int supplierIDValue = Convert.ToInt32(suppliers.SelectedValue);
    bool discontinuedValue = discontinued.Checked;
    // Call the ProductsBLL's UpdateProduct method...
    ProductsBLL productsAPI = new ProductsBLL();
    productsAPI.UpdateProduct(productNameValue, categoryIDValue, supplierIDValue,
                              discontinuedValue, productID);
    // Revert the DataList back to its pre-editing state
    Products.EditItemIndex = -1;
    Products.DataBind();
}

O código começa consultando a Page.IsValid propriedade para garantir que todos os controles de validação na página sejam válidos. Se Page.IsValid for True, o valor do produto editado será ProductID lido da DataKeys coleção e os controles da Web de entrada de dados no EditItemTemplate serão referenciados programaticamente. Em seguida, os valores desses controles da Web são lidos em variáveis que são passadas para a sobrecarga apropriada UpdateProduct . Depois de atualizar os dados, o DataList é retornado ao seu estado de pré-edição.

Observação

Omiti a lógica de tratamento de exceções adicionada no tutorial Manipulando exceções de BLL e DAL-Level para manter o código e este exemplo focados. Como exercício, adicione essa funcionalidade depois de concluir este tutorial.

Etapa 6: Manipulando valores de CategoryID e SupplierID NULL

O banco de dados Northwind permite NULL valores para as Products colunas e SupplierID da CategoryID tabela. No entanto, nossa interface de edição atualmente não acomoda NULL valores. Se tentarmos editar um produto que tenha um NULL valor para suas CategoryID colunas ou SupplierID , obteremos um com uma ArgumentOutOfRangeException mensagem de erro semelhante a: 'Categories' tem um SelectedValue que é inválido porque ele não existe na lista de itens. Além disso, atualmente não há como alterar a categoria ou o valor do fornecedor de um produto de um valor nãoNULL para um NULL .

Para dar suporte NULL a valores para a categoria e o fornecedor DropDownLists, precisamos adicionar um adicional ListItem. Optei por usar (Nenhum) como o Text valor para este ListItem, mas você pode alterá-lo para outra coisa (como uma cadeia de caracteres vazia) se desejar. Por fim, lembre-se de definir DropDownLists AppendDataBoundItems como True; se você esquecer de fazer isso, as categorias e fornecedores associados ao DropDownList substituirão o adicionado estaticamente ListItem.

Depois de fazer essas alterações, a marcação DropDownLists nas Listas de Dados EditItemTemplate deve ser semelhante à seguinte:

<asp:DropDownList ID="Categories" DataSourceID="CategoriesDataSource"
    DataTextField="CategoryName" DataValueField="CategoryID" runat="server"
    SelectedValue='<%# Eval("CategoryID") %>' AppendDataBoundItems="True">
    <asp:ListItem Value=" Selected="True">(None)</asp:ListItem>
</asp:DropDownList>
...
<asp:DropDownList ID="Suppliers" DataSourceID="SuppliersDataSource"
    DataTextField="CompanyName" DataValueField="SupplierID" runat="server"
    SelectedValue='<%# Eval("SupplierID") %>' AppendDataBoundItems="True">
    <asp:ListItem Value=" Selected="True">(None)</asp:ListItem>
</asp:DropDownList>

Observação

S estáticos ListItem podem ser adicionados a um DropDownList por meio do Designer ou diretamente por meio da sintaxe declarativa. Ao adicionar um item DropDownList para representar um valor de banco de dados NULL , adicione o ListItem por meio da sintaxe declarativa. Se você usar o ListItem Editor Coleção no Designer, a sintaxe declarativa gerada omitirá a Value configuração completamente quando for atribuída uma cadeia de caracteres em branco, criando marcação declarativa como: <asp:ListItem>(None)</asp:ListItem>. Embora isso possa parecer inofensivo, o ausente Value faz com que o DropDownList use o valor da Text propriedade em seu lugar. Isso significa que, se isso NULLListItem for selecionado, o valor (Nenhum) tentará ser atribuído ao campo de dados do produto (CategoryID ou SupplierID, neste tutorial), o que resultará em uma exceção. Ao definir Value=""explicitamente , um NULL valor será atribuído ao campo de dados do produto quando o NULLListItem for selecionado.

Reserve um momento para ver nosso progresso por meio de um navegador. Ao editar um produto, observe que e DropDownLists têm uma opção CategoriesSuppliers (None) no início do DropDownList.

As Listas Suspensas de Categorias e Fornecedores incluem uma opção (Nenhum)

Figura 10: o Categories e Suppliers DropDownLists incluem uma opção (Nenhum) (Clique para exibir a imagem em tamanho real)

Para salvar a opção (Nenhum) como um valor de banco de dados NULL , precisamos retornar ao UpdateCommand manipulador de eventos. Altere as categoryIDValue variáveis e supplierIDValue para que sejam inteiros anuláveis e atribua a elas um valor diferente Nothing apenas se dropDownList s SelectedValue não for uma cadeia de caracteres vazia:

int? categoryIDValue = null;
if (!string.IsNullOrEmpty(categories.SelectedValue))
    categoryIDValue = Convert.ToInt32(categories.SelectedValue);
int? supplierIDValue = null;
if (!string.IsNullOrEmpty(suppliers.SelectedValue))
    supplierIDValue = Convert.ToInt32(suppliers.SelectedValue);

Com essa alteração, um valor de Nothing será passado para o UpdateProduct método BLL se o usuário tiver selecionado a opção (Nenhum) de uma das listas suspensas, que corresponde a um NULL valor de banco de dados.

Resumo

Neste tutorial, vimos como criar uma interface de edição datalist mais complexa que incluía três controles Web de entrada diferentes, um TextBox, dois DropDownLists e um CheckBox, juntamente com controles de validação. Ao criar a interface de edição, as etapas são as mesmas, independentemente dos controles da Web que estão sendo usados: comece adicionando os controles da Web à sintaxe DataList; EditItemTemplateuse a sintaxe de associação de dados para atribuir os valores de campo de dados correspondentes com as propriedades de controle da Web apropriadas; e, no UpdateCommand manipulador de eventos, acesse programaticamente os controles da Web e suas propriedades apropriadas, passando seus valores para a BLL.

Ao criar uma interface de edição, seja ela composta apenas por TextBoxes ou uma coleção de diferentes controles da Web, certifique-se de manipular corretamente os valores do banco de dados NULL . Ao considerar NULL s, é imperativo que você não apenas exiba corretamente um valor existente NULL na interface de edição, mas também que você ofereça um meio para marcar um valor como NULL. Para DropDownLists em DataLists, isso normalmente significa adicionar um estático ListItem cuja Value propriedade é definida explicitamente como uma cadeia de caracteres vazia (Value="") e adicionar um pouco de código ao UpdateCommand manipulador de eventos para determinar se o NULL``ListItem foi ou não selecionado.

Programação feliz!

Sobre o autor

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

Agradecimentos Especiais

Esta série de tutoriais foi revisada por muitos revisores úteis. Os principais revisores deste tutorial foram Dennis Patterson, David Suru e Randy Schmidt. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, deixe-me uma linha em mitchell@4GuysFromRolla.com.