Partilhar 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 os controles BoundField, CheckBoxField, HyperLinkField e outros campos de dados. No tutorial anterior , examinamos o uso do TemplateField em um GridView para:

  • Exibir 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 status informações com base nos dados subjacentes. Embora a Employees tabela não contenha uma coluna que retorna o número de dias em que um funcionário esteve no trabalho, pudemos exibir essas informações no exemplo GridView no tutorial anterior com o uso de um método TemplateField e 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 de dados , UnitsInStocke UnitsOnOrder em uma linha DetailsView. O segundo TemplateField exibirá o valor do Discontinued campo, mas usará um método de formatação para exibir "SIM" se Discontinued for truee "NÃO" 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: Associar 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, adicione novos TemplateFields ou converta 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 o único campo de valor booliano (Descontinuado).

Abra a DetailsViewTemplateField.aspx página e arraste 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 GetProducts() método (clique para exibir a imagem em tamanho real)

Para este relatório, SupplierIDremova , ProductID, CategoryIDe ReorderLevel BoundFields. Em seguida, reordene os BoundFields para que o CategoryName e SupplierName BoundFields apareçam imediatamente após o ProductName BoundField. Fique à vontade para ajustar as HeaderText propriedades e as propriedades de formatação para o BoundFields conforme você achar adequado. Assim como no GridView, essas edições no nível 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 propriedade e Width detailsView Height para permitir que o controle DetailsView se expanda com base nos dados exibidos e marcar 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 exibir a página por meio de um navegador. Neste ponto, você deverá ver um único produto listado (Chai) com linhas mostrando o nome do produto, categoria, fornecedor, preço, unidades em estoque, unidades sob encomenda e seus status descontinuados.

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 em ordem 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 campos existentes UnitPrice, UnitsInStocke UnitsOnOrder BoundFields em um TemplateField. Embora eu pessoalmente prefira converter BoundFields existentes, vamos praticar adicionando um novo TemplateField.

Comece clicando no link Editar Campos na marca inteligente DetailsView para abrir a caixa de diálogo Campos. Em seguida, adicione um novo TemplateField e defina sua HeaderText propriedade como "Preço e Inventário" 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 real)

Como esse novo TemplateField conterá os valores exibidos atualmente nos UnitPricecampos , UnitsInStocke UnitsOnOrder BoundFields, vamos removê-los.

A última tarefa para esta etapa é definir a ItemTemplate marcação para o Price and Inventory TemplateField, que pode ser realizado 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 todos os controles da Web da Caixa de Ferramentas.

Para este tutorial, comece adicionando um controle Label ao Price and Inventory TemplateField's ItemTemplate. Em seguida, clique no link Editar DataBindings da marca inteligente do controle Web rótulo e associe a Text propriedade ao UnitPrice campo .

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

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

Formatar o Preço como um Conversor de Moedas

Com essa adição, o Controle Web rótulo Price e 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 exibida por meio de um navegador.

O modelo de preço e inventárioField mostra o preço

Figura 6: o campo Preço e Inventário mostra o preço (clique para exibir a imagem em tamanho real)

Observe que o preço do produto não é 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}. No entanto, para um TemplateField, 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 para a 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 Formatar ou selecionar uma das cadeias de caracteres de formato definidas. Assim como acontece com a propriedade BoundField DataFormatString , a formatação é especificada usando {0:formatSpecifier}.

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

Formatar o Preço como um Conversor de Moedas

Figura 7: formatar o preço como um Conversor de Moedas (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 ou 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 Price and Inventory TemplateField, mas ainda precisamos exibir os UnitsInStock campos e UnitsOnOrder . Vamos exibi-los em uma linha abaixo do preço e entre parênteses. Na interface de edição de modelo 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 da Web de rótulo e a sintaxe de vinculação de dados para que o Price e o Inventory TemplateField exibam as informações de preço e inventário da seguinte maneira:

UnitPrice
(Em Estoque/ Em Ordem: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 inventário em uma única linha DetailsView.

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

Figura 8: As informações de preço e inventário 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 Discontinued tabela é um valor 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 campos de valor não boolianos, como ProductID, ProductNamee assim por diante, são implementados como BoundFields. O CheckBoxField é renderizado como uma caixa de seleção desabilitada que é verificada se o valor do campo de dados é True e desmarcado de outra forma.

Em vez de exibir o CheckBoxField, talvez queiramos exibir 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. Tire 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 queríamos que as cadeias de caracteres "True" ou "False" fossem usadas, mas "SIM" e "NÃO", em vez disso. Essa personalização pode ser executada com o auxílio de um TemplateField e um método de formatação. Um método de formatação pode receber 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 um 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";
}

Esse método verifica o parâmetro de entrada (discontinued) e retorna "SIM" se for true, caso contrário, "NÃO".

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, necessário para marcar se o valor da propriedade do HiredDate funcionário tinha um valor de banco de dados NULL antes de acessar a EmployeesRowpropriedade do HiredDate . Esse marcar não é necessário 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 booliano 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 do TemplateField.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 por meio 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 Eval valor retornado dos métodos para bool. Em DisplayDiscontinuedAsYESorNO seguida, o método retornará "SIM" ou "NÃO", dependendo do valor recebido. O valor retornado é o que é exibido nesta linha DetailsView (consulte a Figura 10).

Os valores YES ou NO 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 o 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 da Web em vez de texto sem formatação
  • A saída depende dos dados subjacentes, como exibir metadados ou reformatar os dados

Embora TemplateFields permita um maior grau de flexibilidade na renderização dos dados subjacentes do DetailsView, a saída detailsView ainda parece um pouco boxy, 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.

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. O revisor principal deste tutorial foi Dan Jagers. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, deixe-me uma linha em mitchell@4GuysFromRolla.com.