Compartilhar via


Uso de TemplateFields no controle DetailsView (C#)

por Scott Mitchell

Baixar PDF

Os mesmos recursos TemplateFields disponíveis com o GridView também estão disponíveis com o controle DetailsView. Neste tutorial, exibiremos um produto por vez usando um DetailsView contendo TemplateFields.

Introdução

O TemplateField oferece um grau mais alto de flexibilidade na renderização de dados do que o BoundField, CheckBoxField, HyperLinkField e outros controles de campo de dados. No tutorial anterior, vimos como usar o TemplateField em um GridView para:

  • Exiba vários valores de campo de dados em uma coluna. Especificamente, os FirstName campos e LastName foram combinados em uma coluna GridView.
  • Use um controle Web alternativo para expressar um valor de campo de dados. Vimos como mostrar o HiredDate valor usando um controle Calendar.
  • Mostrar informações de status com base nos dados subjacentes. Embora a Employees tabela não contenha uma coluna que retorne o número de dias que um funcionário esteve no trabalho, pudemos exibir essas informações no exemplo GridView no tutorial anterior com o uso de um TemplateField e um método de formatação.

Os mesmos recursos TemplateFields disponíveis com o GridView também estão disponíveis com o controle DetailsView. Neste tutorial, exibiremos um produto por vez usando um DetailsView que contém dois TemplateFields. O primeiro TemplateField combinará os UnitPricecampos , UnitsInStocke UnitsOnOrder data em uma linha DetailsView. O segundo TemplateField exibirá o valor do campo, mas usará um método de Discontinued formatação para exibir "YES" se Discontinued for true, e "NO" caso contrário.

Dois TemplateFields são usados para personalizar a exibição

Figura 1: Dois TemplateFields são usados para personalizar a exibição (clique para exibir a imagem em tamanho real)

Vamos começar!

Etapa 1: Associando os dados ao DetailsView

Conforme discutido no tutorial anterior, ao trabalhar com TemplateFields, geralmente é mais fácil começar criando o controle DetailsView que contém apenas BoundFields e, em seguida, adicionar novos TemplateFields ou converter os BoundFields existentes em TemplateFields conforme necessário. Portanto, inicie este tutorial adicionando um DetailsView à página por meio do Designer e associando-o a um ObjectDataSource que retorna a lista de produtos. Essas etapas criarão um DetailsView com BoundFields para cada um dos campos de valor não booliano do produto e um CheckBoxField para um campo de valor booleano (Descontinuado).

Abra a DetailsViewTemplateField.aspx página e arraste um DetailsView da Caixa de Ferramentas para o Designer. Na marca inteligente do DetailsView, escolha adicionar um novo controle ObjectDataSource que invoca o ProductsBLL método da GetProducts() classe.

Adicionar um novo controle ObjectDataSource que invoca o método GetProducts()

Figura 2: Adicionar um novo controle ObjectDataSource que invoca o método (clique para exibir a GetProducts() imagem em tamanho completo)

Para este relatório, remova o ProductID, SupplierID, CategoryIDe ReorderLevel BoundFields. Em seguida, reordene os BoundFields para que os CategoryName e SupplierName BoundFields apareçam imediatamente após o ProductName BoundField. Sinta-se à vontade para ajustar as propriedades e as HeaderText propriedades de formatação dos BoundFields como achar melhor. Assim como no GridView, essas edições no nível do BoundField podem ser executadas por meio da caixa de diálogo Campos (acessível clicando no link Editar Campos na marca inteligente do DetailsView) ou por meio da sintaxe declarativa. Por fim, desmarque os valores de Height propriedade e Width DetailsView para permitir que o controle DetailsView se expanda com base nos dados exibidos e marque a caixa de seleção Habilitar paginação na marca inteligente.

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

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"
    EnableViewState="False">
    <Fields>
        <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" />
        <asp:BoundField DataField="QuantityPerUnit"
          HeaderText="Qty/Unit" SortExpression="QuantityPerUnit" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
          SortExpression="UnitPrice" />
        <asp:BoundField DataField="UnitsInStock"
          HeaderText="Units In Stock" SortExpression="UnitsInStock" />
        <asp:BoundField DataField="UnitsOnOrder"
          HeaderText="Units On Order" SortExpression="UnitsOnOrder" />
        <asp:CheckBoxField DataField="Discontinued"
          HeaderText="Discontinued" SortExpression="Discontinued" />
    </Fields>
</asp:DetailsView>

Reserve um momento para visualizar a página por meio de um navegador. Neste ponto, você deve ver um único produto listado (Chai) com linhas mostrando o nome do produto, categoria, fornecedor, preço, unidades em estoque, unidades em pedido e seu status descontinuado.

Os detalhes do produto são mostrados usando uma série de BoundFields

Figura 3: Os detalhes do produto são mostrados usando uma série de BoundFields (clique para exibir a imagem em tamanho real)

Etapa 2: Combinando o preço, as unidades em estoque e as unidades no pedido em uma linha

O DetailsView tem uma linha para os UnitPricecampos , UnitsInStocke .UnitsOnOrder Podemos combinar esses campos de dados em uma única linha com um TemplateField adicionando um novo TemplateField ou convertendo um dos , , e e UnitsOnOrder BoundFields existentes UnitPriceUnitsInStockem um TemplateField. Embora eu pessoalmente prefira converter BoundFields existentes, vamos praticar adicionando um novo TemplateField.

Comece clicando no link Editar campos na marca inteligente do DetailsView para abrir a caixa de diálogo Campos. Em seguida, adicione um novo TemplateField e defina sua HeaderText propriedade como "Preço e Estoque" e mova o novo TemplateField para que ele seja posicionado acima do UnitPrice BoundField.

Adicionar um novo TemplateField ao controle DetailsView

Figura 4: Adicionar um novo TemplateField ao controle DetailsView (clique para exibir a imagem em tamanho completo)

Como esse novo TemplateField conterá os valores atualmente exibidos em , UnitPriceUnitsInStock, e BoundFieldsUnitsOnOrder, vamos removê-los.

A última tarefa desta etapa é definir a ItemTemplate marcação para o Price and Inventory TemplateField, o que pode ser feito por meio da interface de edição de modelo do DetailsView no Designer ou manualmente por meio da sintaxe declarativa do controle. Assim como acontece com o GridView, a interface de edição de modelo do DetailsView pode ser acessada clicando no link Editar Modelos na marca inteligente. A partir daqui, você pode selecionar o modelo a ser editado na lista suspensa e, em seguida, adicionar quaisquer controles Web da Caixa de Ferramentas.

Para este tutorial, comece adicionando um controle Rótulo ao arquivo .ItemTemplate Em seguida, clique no link Editar DataBindings da marca inteligente do controle Web de Rótulo e associe a Text propriedade ao UnitPrice campo.

Associar a propriedade de texto do rótulo ao campo de dados UnitPrice

Figura 5: Associar a propriedade do Text rótulo ao campo de dados (clique para exibir a UnitPrice imagem em tamanho real)

Formatando o preço como uma moeda

Com essa adição, o Label Web control Price and Inventory TemplateField agora exibirá apenas o preço do produto selecionado. A Figura 6 mostra uma captura de tela do nosso progresso até agora quando visualizado por meio de um navegador.

O campo Modelo de preço e inventário mostra o preço

Figura 6: O campo Modelo de preço e estoque mostra o preço (clique para exibir a imagem em tamanho real)

Observe que o preço do produto não está formatado como uma moeda. Com um BoundField, a formatação é possível definindo a HtmlEncode propriedade como false e a DataFormatString propriedade como {0:formatSpecifier}. Para um TemplateField, no entanto, todas as instruções de formatação devem ser especificadas na sintaxe de vinculação de dados ou por meio do uso de um método de formatação definido em algum lugar dentro do código do aplicativo (como na classe code-behind da página ASP.NET).

Para especificar a formatação da sintaxe de vinculação de dados usada no controle Web Rótulo, retorne à caixa de diálogo DataBindings clicando no link Editar DataBindings da marca inteligente do Rótulo. Você pode digitar as instruções de formatação diretamente na lista suspensa Formato ou selecionar uma das cadeias de caracteres de formato definidas. Assim como a propriedade do BoundField DataFormatString , a formatação é especificada usando {0:formatSpecifier}.

Para o campo, UnitPrice use a formatação de moeda especificada selecionando o valor da lista suspensa apropriada ou digitando {0:C} manualmente.

Formatar o preço como uma moeda

Figura 7: Formatar o preço como uma moeda (clique para exibir a imagem em tamanho real)

Declarativamente, a especificação de formatação é indicada como um segundo parâmetro nos Bind métodos or Eval . As configurações feitas por meio do Designer resultam na seguinte expressão de vinculação de dados na marcação declarativa:

<asp:Label ID="Label1" runat="server" Text='<%# Eval("UnitPrice", "{0:C}") %>'/>

Adicionando os campos de dados restantes ao TemplateField

Neste ponto, exibimos e formatamos o UnitPrice campo de dados no campo Modelo de preço e estoque, mas ainda precisamos exibir os UnitsInStock campos e UnitsOnOrder . Vamos exibi-los em uma linha abaixo do preço e entre parênteses. A partir da interface de edição de modelos no Designer, essa marcação pode ser adicionada posicionando o cursor dentro do modelo e simplesmente digitando o texto a ser exibido. Como alternativa, essa marcação pode ser inserida diretamente na sintaxe declarativa.

Adicione a marcação estática, os controles Web de rótulo e a sintaxe de vinculação de dados para que o Price and Inventory TemplateField exiba as informações de preço e estoque da seguinte forma:

UnitPrice
(Em estoque / Sob encomenda: UnitsInStock / UnitsOnOrder)

Depois de executar essa tarefa, a marcação declarativa do DetailsView deve ser semelhante à seguinte:

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"
    EnableViewState="False">
    <Fields>
        <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" />
        <asp:BoundField DataField="QuantityPerUnit"
          HeaderText="Qty/Unit" SortExpression="QuantityPerUnit" />
        <asp:TemplateField HeaderText="Price and Inventory">
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server"
                  Text='<%# Eval("UnitPrice", "{0:C}") %>'></asp:Label>
                <br />
                <strong>
                (In Stock / On Order: </strong>
                <asp:Label ID="Label2" runat="server"
                  Text='<%# Eval("UnitsInStock") %>'></asp:Label>
                <strong>/</strong>
                <asp:Label ID="Label3" runat="server"
                  Text='<%# Eval("UnitsOnOrder") %>'>
                </asp:Label><strong>)</strong>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:CheckBoxField DataField="Discontinued"
           HeaderText="Discontinued" SortExpression="Discontinued" />
    </Fields>
</asp:DetailsView>

Com essas alterações, consolidamos as informações de preço e estoque em uma única linha DetailsView.

As informações de preço e estoque são exibidas em uma única linha

Figura 8: As informações de preço e estoque são exibidas em uma única linha (clique para exibir a imagem em tamanho real)

Etapa 3: Personalizando as informações de campo descontinuadas

A Products coluna da tabela é um valor de Discontinued bit que indica se o produto foi descontinuado. Ao associar um DetailsView (ou GridView) a um controle de fonte de dados, os campos de valor booliano, como Discontinued, são implementados como CheckBoxFields, enquanto os campos de valor não booliano, como ProductID, ProductNamee assim por diante, são implementados como BoundFields. O CheckBoxField é renderizado como uma caixa de seleção desativada que é marcada se o valor do campo de dados for True e desmarcada caso contrário.

Em vez de exibir o CheckBoxField, talvez queiramos exibir um texto indicando se o produto foi descontinuado ou não. Para fazer isso, podemos remover o CheckBoxField do DetailsView e, em seguida, adicionar um BoundField cuja DataField propriedade foi definida como Discontinued. Reserve um momento para fazer isso. Após essa alteração, o DetailsView mostra o texto "True" para produtos descontinuados e "False" para produtos que ainda estão ativos.

As cadeias de caracteres true e false são usadas para exibir o estado descontinuado

Figura 9: As cadeias de caracteres true e false são usadas para exibir o estado descontinuado (clique para exibir a imagem em tamanho real)

Imagine que não quiséssemos que as strings "True" ou "False" fossem usadas, mas sim "SIM" e "NÃO". Essa personalização pode ser realizada com a ajuda de um TemplateField e um método de formatação. Um método de formatação pode incluir qualquer número de parâmetros de entrada, mas deve retornar o HTML (como uma cadeia de caracteres) para injetar no modelo.

Adicione um método de formatação à DetailsViewTemplateField.aspx classe code-behind da página chamada DisplayDiscontinuedAsYESorNO que aceita um booliano como parâmetro de entrada e retorna uma cadeia de caracteres. Conforme discutido no tutorial anterior, esse método deve ser marcado como protected ou public para ser acessível a partir do modelo.

protected string DisplayDiscontinuedAsYESorNO(bool discontinued)
{
    if (discontinued)
        return "YES";
    else
        return "NO";
}

Este método verifica o parâmetro de entrada (discontinued) e retorna "YES" se for true, "NO" caso contrário.

Observação

No método de formatação examinado no tutorial anterior, lembre-se de que estávamos passando um campo de dados que poderia conter NULL s e, portanto, precisávamos verificar se o valor da propriedade do HiredDate funcionário tinha um valor de banco de dados NULL antes de acessar a EmployeesRowpropriedade do HiredDate . Essa verificação não é necessária aqui, pois a Discontinued coluna nunca pode ter valores de banco de dados NULL atribuídos. Além disso, é por isso que o método pode aceitar um parâmetro de entrada booleano em vez de ter que aceitar uma ProductsRow instância ou um parâmetro do tipo object.

Com esse método de formatação concluído, tudo o que resta é chamá-lo a partir do arquivo .ItemTemplate Para criar o TemplateField, remova o Discontinued BoundField e adicione um novo TemplateField ou converta o Discontinued BoundField em um TemplateField. Em seguida, na exibição de marcação declarativa, edite o TemplateField para que ele contenha apenas um ItemTemplate que invoca o DisplayDiscontinuedAsYESorNO método, passando o valor da propriedade da Discontinued instância atualProductRow. Isso pode ser acessado através do Eval método. Especificamente, a marcação do TemplateField deve ser semelhante a:

<asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
    <ItemTemplate>
        <%# DisplayDiscontinuedAsYESorNO((bool)
          Eval("Discontinued")) %>
    </ItemTemplate>
</asp:TemplateField>

Isso fará com que o DisplayDiscontinuedAsYESorNO método seja invocado ao renderizar o DetailsView, passando o ProductRow valor da Discontinued instância. Como o Eval método retorna um valor do tipo object, mas o DisplayDiscontinuedAsYESorNO método espera um parâmetro de entrada do tipo bool, convertemos o valor de retorno dos Eval métodos para bool. O DisplayDiscontinuedAsYESorNO método retornará "SIM" ou "NÃO" dependendo do valor recebido. O valor retornado é o que é exibido nessa linha DetailsView (consulte a Figura 10).

Os valores SIM ou NÃO agora são mostrados na linha Descontinuada

Figura 10: Os valores SIM ou NÃO agora são mostrados na linha descontinuada (clique para exibir a imagem em tamanho real)

Resumo

O TemplateField no controle DetailsView permite um maior grau de flexibilidade na exibição de dados do que está disponível com os outros controles de campo e é ideal para situações em que:

  • Vários campos de dados precisam ser exibidos em uma coluna GridView
  • Os dados são melhor expressos usando um controle Web em vez de texto sem formatação
  • A saída depende dos dados subjacentes, como a exibição de metadados ou a reformatação dos dados

Embora TemplateFields permita um maior grau de flexibilidade na renderização dos dados subjacentes do DetailsView, a saída do DetailsView ainda parece um pouco quadrada, pois cada campo é renderizado como uma linha em um HTML <table>.

O controle FormView oferece um maior grau de flexibilidade na configuração da saída renderizada. O FormView não contém campos, mas apenas uma série de modelos (ItemTemplate, EditItemTemplate, HeaderTemplatee assim por diante). Veremos como usar o FormView para obter ainda mais controle do layout renderizado em nosso próximo tutorial.

Boa programação!

Sobre o autor

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

Agradecimentos especiais a

Esta série de tutoriais foi revisada por muitos revisores úteis. O revisor principal deste tutorial foi Dan Jagers. Interessado em revisar meus próximos artigos do MSDN? Em caso afirmativo, envie-me uma mensagem para mitchell@4GuysFromRolla.com.