Partilhar via


Personalizando a interface de edição da DataList (C#)

por Scott Mitchell

Descarregar PDF

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

Introdução

A marcação HTML e os controlos Web no DataList EditItemTemplate definem a sua interface editável. Em todos os exemplos editáveis de DataList que examinamos até agora, a interface editável foi composta de controles 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 para incluir controles da Web diferentes do TextBox, como DropDownLists, RadioButtonLists, Calendars e assim por diante. Como com TextBoxes, ao personalizar a interface de edição para incluir outros controles da Web, empregue as seguintes etapas:

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

Neste tutorial, criaremos uma interface de edição mais rica para a DataList, 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 o status descontinuado 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 visualizar 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, a partir do Designer, adicione uma DataList à página, definindo sua ID propriedade como Products. A partir da marca inteligente DataList, crie um novo ObjectDataSource. Nomeie esse novo ObjectDataSource ProductsDataSource e configure-o para recuperar dados do ProductsBLL método s GetProducts da classe. Como nos tutoriais editáveis anteriores da DataList, atualizaremos as informações do produto editado indo diretamente para a camada de lógica de negócios. Assim, configure as caixas de opções nas guias UPDATE, INSERT e DELETE como Nenhum.

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

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

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

<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 apresenta as informações do produto usando um <título h4> para o nome do produto e 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 visualizado através de um navegador.

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

Figura 3: O nome, fornecedor, categoria, status descontinuado e preço de cada produto é exibido (Clique para visualizar a imagem em tamanho real)

Etapa 2: Adicionando 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 uma DropDownList para a categoria, outra 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 Label Web.

Para personalizar a interface de edição, clique na ligação Editar Templates da marca inteligente DataList e escolha a opção EditItemTemplate na lista suspensa. Adicione um DropDownList ao EditItemTemplate e defina o seu ID como Categories.

Adicionar uma DropDownList para as categorias

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

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

Criar um novo ObjectDataSource chamado CategoriesDataSource

Figura 5: Criar um novo ObjectDataSource nomeado CategoriesDataSource (Clique para visualizar a imagem em tamanho real)

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

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

Repita esta série de etapas para criar uma 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 o 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 estejam definidas como Atualizar e Cancelar, respectivamente.

Sinta-se à vontade para definir a interface de edição como quiser. 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 está disposta como a interface Read-Only (Clique para visualizar a imagem em tamanho real)

Etapa 3: Criando os manipuladores de eventos EditCommand e CancelCommand

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

Crie esses dois manipuladores de eventos e faça com que eles usem 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 no lugar, 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 a lista de dados depois de clicar no botão Edit para o Gumbo Mix do Chef Anton. Como ainda não adicionamos nenhuma sintaxe de vinculação de dados à interface de edição, a ProductName TextBox está em branco, a Discontinued CheckBox desmarcada e os primeiros itens selecionados nas Categories e Suppliers DropDownLists.

Captura de tela mostrando o DataList EditItemTemplate 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 visualizar 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 vinculação de dados para atribuir os valores do campo de dados aos valores de controle da Web apropriados. A sintaxe de associação de dados pode ser aplicada através do Designer, acedendo à tela Editar Modelos e selecionando o link Editar DataBindings nas tags inteligentes dos controlos Web. Como alternativa, a sintaxe de vinculação de dados pode ser adicionada diretamente à marcação declarativa.

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

Captura de tela mostrando o DataList EditItemTemplate 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 visualizar a imagem em tamanho real)

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

Quando o utilizador edita um produto e clica no botão Atualizar, ocorre um postback e o evento DataList é disparado. No gestor de eventos, temos de ler os valores dos controlos na Web em EditItemTemplate e interagir com a BLL para atualizar o produto na base de dados. Como vimos em tutoriais anteriores, o produto atualizado ProductID é acessível através da coleção DataKeys. Os campos inseridos pelo usuário são acessados referenciando programaticamente os controles da Web usando FindControl("controlID"), como mostra o código a seguir:

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 é True, o produto editado tem o valor ProductID lido da coleção DataKeys e os controles Web de entrada de dados no EditItemTemplate sã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: Lidando com os valores nulos de CategoryID e SupplierID

O banco de dados Northwind permite valores para NULL a tabela Products e as colunas CategoryID e SupplierID. 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 ou SupplierID colunas, obteremos uma ArgumentOutOfRangeException mensagem de erro semelhante a: 'Categories' tem um SelectedValue que é inválido porque não existe na lista de itens. Além disso, atualmente não há como alterar a categoria de um produto ou o valor do fornecedor de um não-valorNULL para um NULL .

Para suportar NULL valores para as listas suspensas de categoria e fornecedor, precisamos adicionar um ListItem. Eu escolhi usar (Nenhum) como o valor Text para este ListItem, mas pode alterá-lo para outra coisa (como uma cadeia de caracteres vazia) se assim desejar. Por fim, lembre-se de definir o DropDownLists AppendDataBoundItems como True. Se o leitor se esquecer de fazê-lo, as categorias e fornecedores vinculados ao DropDownLists substituirão o ListItem adicionado estaticamente.

Depois de fazer essas alterações, a marcação DropDownLists no DataList s 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

Static ListItem s pode ser adicionado a um DropDownList através do Designer ou diretamente através da sintaxe declarativa. Ao adicionar um item à DropDownList para representar um valor de banco de dados NULL, certifique-se de o fazer através da sintaxe declarativa ListItem. Se usar o Editor de Coleções no Designer, a sintaxe declarativa gerada omitirá completamente a configuração ListItem quando for atribuída uma cadeia de texto vazia, criando uma marcação declarativa como: Value. Embora isso possa parecer inofensivo, a falta Value faz com que o DropDownList use o valor da propriedade Text em seu lugar. Isso significa que, se isso NULLListItem for selecionado, o valor (Nenhum) será tentado para 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 o nosso progresso através de um navegador. Quando editar um produto, observe que as Categories e Suppliers DropDownLists têm uma opção (Nenhuma) no início das DropDownLists.

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

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

Para salvar a opção (Nenhum) como um valor de banco de dados NULL , precisamos retornar ao manipulador de UpdateCommand eventos. Altere as variáveis categoryIDValue e supplierIDValue para serem inteiros anuláveis e atribua-lhes um valor diferente de Nothing apenas se o DropDownList 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 esta alteração, um valor de Nothing será passado para o método BLL UpdateProduct se o utilizador selecionar a opção (Nenhum) em qualquer uma das listas suspensas, o que corresponde a um valor de base de dados NULL.

Resumo

Neste tutorial, vimos como criar uma interface de edição DataList mais complexa que incluía três controles da Web de entrada diferentes: uma TextBox, duas DropDownLists, e uma 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 aos controles da DataList; use a sintaxe de vinculação de dados para atribuir os valores de campo de dados correspondentes com as propriedades de controle da Web apropriadas; e, no EditItemTemplate manipulador de eventos, acesse programaticamente os controles da Web e suas propriedades apropriadasUpdateCommand, passando os 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 contabilizar NULL s, é imperativo que você não apenas exiba corretamente um valor existente NULL na interface de edição, mas também que ofereça um meio para marcar um valor como NULL. Para DropDownLists em DataLists, isso normalmente significa adicionar uma estática ListItem cuja Value propriedade é explicitamente definida 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 selecionado ou não.

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 deste tutorial foram Dennis Patterson, David Suru e Randy Schmidt. Interessado em rever meus próximos artigos do MSDN? Se for o caso, envie-me uma mensagem para mitchell@4GuysFromRolla.com.