Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
por Scott Mitchell
Os mesmos recursos TemplateFields disponíveis com o GridView também estão disponíveis com o controle DetailsView. Neste tutorial, exibiremos um produto de cada vez usando um DetailsView contendo TemplateFields.
Introdução
O TemplateField oferece um maior grau de flexibilidade na renderização de dados do que os controles BoundField, CheckBoxField, HyperLinkField e outros campos de dados. No tutorial anterior , analisamos o uso do TemplateField em um GridView para:
- Exiba vários valores de campo de dados em uma coluna. Especificamente, os
FirstNamecampos eLastNameforam combinados em uma coluna GridView. - Use um controlador da Web alternativo para expressar um valor de um campo de dados. Vimos como mostrar o
HiredDatevalor usando um controle Calendar. - Mostrar informações de status com base nos dados subjacentes. Embora a
Employeestabela 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 de cada vez usando um DetailsView que contém dois TemplateFields. O primeiro TemplateField combinará os campos de dados UnitPrice, UnitsInStock e UnitsOnOrder numa linha DetailsView. O segundo TemplateField exibirá o valor do campo Discontinued, mas usará um método de formatação para exibir "SIM" se Discontinued for true, e "NÃO" caso contrário.
Figura 1: Dois TemplateFields são usados para personalizar a exibição (Clique para visualizar a imagem em tamanho real)
Vamos começar!
Etapa 1: Vinculando os dados ao DetailsView
Como 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 vinculando-o a um ObjectDataSource que retorna a lista de produtos. Esses passos vão criar um DetailsView com campos BoundFields para cada um dos campos de valor não booleano do produto e um campo CheckBoxField para o único campo de valor booleano (Descontinuado).
Abra a página DetailsViewTemplateField.aspx e arraste um DetailsView da Caixa de Ferramentas para o Designer. Na etiqueta inteligente do DetailsView, opte por adicionar um novo controle ObjectDataSource que invoque o método da classe ProductsBLLGetProducts().
Figura 2: Adicionar um novo controle ObjectDataSource que invoca o método (GetProducts() imagem em tamanho real)
Para este relatório, remova o ProductID, SupplierID, CategoryID e ReorderLevel BoundFields. Em seguida, reordene os BoundFields para que o CategoryName e SupplierName BoundFields apareçam imediatamente após o ProductName BoundField. Sinta-se à vontade para ajustar as propriedades dos BoundFields e as propriedades de formatação conforme achar melhor. Como no GridView, essas edições no nível de BoundField podem ser editadas por meio da caixa de diálogo Campos (acessível clicando no link Editar campos na etiqueta inteligente do DetailsView) ou por meio da sintaxe declarativa. Por fim, limpe os valores das propriedades Height e Width do DetailsView para permitir que o controle DetailsView se expanda com base nos dados exibidos, e marque a caixa de seleção Ativar 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 através de um navegador. Neste ponto, você verá um único produto listado (Chai) com linhas mostrando o nome, categoria, fornecedor, preço, unidades em estoque, unidades em pedido e seu status descontinuado do produto.
Figura 3: Os detalhes do produto são mostrados usando uma série de BoundFields (Clique para visualizar a imagem em tamanho real)
Etapa 2: Combinando o preço, as unidades em estoque e as unidades sob encomenda em uma linha
O DetailsView tem uma linha para os campos UnitPrice, UnitsInStock e UnitsOnOrder. Podemos combinar esses campos de dados em uma única linha com um TemplateField adicionando um novo TemplateField ou convertendo um dos existentes UnitPrice, UnitsInStock, e UnitsOnOrder BoundFields em um TemplateField. Embora eu pessoalmente prefira converter BoundFields existentes, vamos praticar adicionando um novo TemplateField.
Comece por clicar no link Editar campos no smart tag do DetailsView para abrir a caixa de diálogo Campos. Em seguida, adicione um novo TemplateField e defina sua HeaderText propriedade como "Price and Inventory" e mova o novo TemplateField para que ele fique posicionado acima do UnitPrice BoundField.
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 no UnitPrice, 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 realizada por meio da interface de edição de modelo do DetailsView no Designer ou manualmente por meio da sintaxe declarativa do controle. Tal como acontece com o GridView, a interface de edição de modelos do DetailsView pode ser acedida clicando na ligação Editar modelos na etiqueta inteligente. A partir daqui, pode selecionar o modelo a editar na lista suspensa e, em seguida, adicionar quaisquer controlos da Web a partir da Caixa de Ferramentas.
Para este tutorial, comece adicionando um controle Label ao Price and Inventory TemplateField's ItemTemplate. Em seguida, clique no link Edit DataBindings da tag inteligente do controlo Web da etiqueta e vincule a propriedade Text ao campo UnitPrice.
Figura 5: Vincular a propriedade do Text rótulo ao campo de dados (UnitPrice imagem em tamanho real)
Formatando o preço como 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 através de um navegador.
Figura 6: O modelo de preço e inventárioField mostra o preço (Clique para visualizar 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 através 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 Label Web, retorne à caixa de diálogo DataBindings clicando no link Edit DataBindings da marca inteligente do Label. Você pode digitar as instruções de formatação diretamente na lista suspensa Formato ou selecionar uma das cadeias de caracteres de formato definidas. Como na propriedade BoundField DataFormatString , a formatação é especificada usando {0:formatSpecifier}.
Para o campo UnitPrice, use a formatação de moeda especificada, seja selecionando o valor apropriado da lista suspensa ou digitando {0:C} manualmente.
Figura 7: Formatar o preço como moeda (Clique para visualizar a imagem em tamanho real)
Declarativamente, a especificação de formatação é indicada como um segundo parâmetro nos métodos Bind 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 campo de dados UnitPrice no campo modelo de preço e inventário, mas ainda precisamos exibir os campos UnitsInStock e UnitsOnOrder. Vamos exibi-los em uma linha abaixo do preço e entre parênteses. A partir da 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 Label e a sintaxe de vinculação de dados para que o Price and Inventory TemplateField exiba as informações de preço e inventário da seguinte forma:
Preço unitário
(Em Stock / Sob Encomenda:UnitsInStock / UnidadesSobEncomenda)
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.
Figura 8: As informações de preço e inventário são exibidas em uma única linha (Clique para visualizar a imagem em tamanho real)
Etapa 3: Personalizando as informações de campo descontinuadas
A Products coluna da Discontinued tabela é um valor de bit que indica se o produto foi descontinuado. Ao vincular um DetailsView (ou GridView) a um controle de fonte de dados, os campos de valor booleano, como Discontinued, são implementados como CheckBoxFields, enquanto campos de valor não booleanos, como ProductID, ProductNamee assim por diante, são implementados como BoundFields. O CheckBoxField é renderizado como uma caixa de seleção desabilitada que é marcada se o valor do campo de dados for True e desmarcada caso contrário.
Em vez de exibir o CheckBoxField, podemos querer exibir texto indicando se o produto foi descontinuado ou não. Para fazer isso, poderíamos 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.
Figura 9: As cadeias de caracteres true e false são usadas para exibir o estado descontinuado (Clique para visualizar a imagem em tamanho real)
Imagine que não queríamos que as strings "True" ou "False" fossem usadas, mas sim "YES" e "NO", em vez disso. Tal personalização pode ser realizada 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 Boolean 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";
}
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 NULLs e, portanto, era necessário verificar se o valor da propriedade do HiredDate tinha um valor de banco de dados NULL antes de acessar a propriedade de EmployeesRow do HiredDate. Essa verificação não é necessária aqui, uma vez que 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 este método de formatação concluído, tudo o que resta é chamá-lo a partir do TemplateField's 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 vista de marcação declarativa, edite o TemplateField para que ele contenha apenas um ItemTemplate que invoca o método DisplayDiscontinuedAsYESorNO, passando o valor da propriedade ProductRow da instância Discontinued atual. Isso pode ser acessado através do Eval método. Especificamente, a marcação do TemplateField deve ter a seguinte aparência:
<asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
<ItemTemplate>
<%# DisplayDiscontinuedAsYESorNO((bool)
Eval("Discontinued")) %>
</ItemTemplate>
</asp:TemplateField>
Isso fará com que o método DisplayDiscontinuedAsYESorNO seja invocado ao renderizar o DetailsView, passando o ProductRow valor da instância Discontinued. 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, nós convertemos o Eval valor de retorno dos métodos para bool. O DisplayDiscontinuedAsYESorNO método retornará "SIM" ou "NÃO", dependendo do valor que receber. O valor retornado é o que é exibido nesta linha DetailsView (consulte a Figura 10).
Figura 10: Os valores SIM ou NÃO agora são mostrados na linha descontinuada (Clique para visualizar a imagem em tamanho normal)
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 são ideais 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 a exibição de metadados ou a reformatação dos dados
Embora os TemplateFields permitam um maior grau de flexibilidade na renderização dos dados subjacentes do DetailsView, a saída do DetailsView ainda parece um pouco rígida, já que 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, HeaderTemplate, e assim por diante). Veremos como usar o FormView para obter ainda mais controle do layout renderizado em nosso próximo tutorial.
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. O revisor principal deste tutorial foi Dan Jagers. Interessado em rever meus próximos artigos do MSDN? Se for o caso, envie-me uma mensagem para mitchell@4GuysFromRolla.com.