Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
por Scott Mitchell
Este tutorial expande a relação master/detalhes para adicionar uma terceira camada, usando dois controles DropDownList para selecionar os registros pai e avô desejados.
Introdução
No tutorial anterior, examinamos como exibir um relatório simples de master/detalhes usando um único DropDownList preenchido com as categorias e um GridView mostrando os produtos que pertencem à categoria selecionada. Esse padrão de relatório funciona bem ao exibir registros que têm uma relação um-para-muitos e podem ser facilmente estendidos para funcionar em cenários que incluem várias relações um-para-muitos. Por exemplo, um sistema de entrada de pedidos teria tabelas que correspondem a clientes, pedidos e itens de linha de pedido. Um determinado cliente pode ter vários pedidos com cada pedido que consiste em vários itens. Esses dados podem ser apresentados ao usuário com dois DropDownLists e um GridView. O primeiro DropDownList teria um item de lista para cada cliente no banco de dados com o conteúdo do segundo sendo os pedidos feitos pelo cliente selecionado. Um GridView listaria os itens de linha da ordem selecionada.
Embora o banco de dados Northwind inclua as informações canônicas de detalhes do cliente/pedido/pedido em suas Customers
tabelas , Orders
e Order Details
, essas tabelas não são capturadas em nossa arquitetura. No entanto, ainda podemos ilustrar o uso de duas DropDownLists dependentes. O primeiro DropDownList listará as categorias e a segunda os produtos pertencentes à categoria selecionada. Um DetailsView listará os detalhes do produto selecionado.
Etapa 1: Criando e populando as categorias DropDownList
Nossa primeira meta é adicionar o DropDownList que lista as categorias. Essas etapas foram examinadas detalhadamente no tutorial anterior, mas são resumidas aqui para fins de integridade.
Abra a MasterDetailsDetails.aspx
página na Filtering
pasta, adicione um DropDownList à página, defina sua ID
propriedade como Categories
e clique no link Configurar Fonte de Dados em sua marca inteligente. No Assistente de Configuração da Fonte de Dados, escolha adicionar uma nova fonte de dados.
Figura 1: Adicionar uma nova fonte de dados para o DropDownList (clique para exibir a imagem em tamanho real)
A nova fonte de dados deve, naturalmente, ser um ObjectDataSource. Nomeie este novo ObjectDataSource CategoriesDataSource
e faça com que ele invoque o CategoriesBLL
método do GetCategories()
objeto.
Figura 2: Escolher usar a CategoriesBLL
classe (clique para exibir a imagem em tamanho real)
Figura 3: Configurar o ObjectDataSource para usar o GetCategories()
método (clique para exibir a imagem em tamanho real)
Depois de configurar o ObjectDataSource, ainda precisamos especificar qual campo de fonte de dados deve ser exibido no Categories
DropDownList e qual deles deve ser configurado como o valor do item de lista. Defina o CategoryName
campo como a exibição e CategoryID
como o valor de cada item de lista.
Figura 4: Fazer com que DropDownList exiba o CategoryName
campo e use CategoryID
como o valor (clique para exibir a imagem em tamanho real)
Neste ponto, temos um controle DropDownList (Categories
) que é preenchido com os registros da Categories
tabela. Quando o usuário escolher uma nova categoria do DropDownList, queremos que ocorra um postback para atualizar o DropDownList do produto que criaremos na Etapa 2. Portanto, marcar a opção Habilitar AutoPostBack da categories
marca inteligente dropDownList.
Figura 5: Habilitar o AutoPostBack para DropDownList Categories
(clique para exibir a imagem em tamanho real)
Etapa 2: Exibindo os produtos da categoria selecionada em uma segunda lista suspensa
Com o Categories
DropDownList concluído, nossa próxima etapa é exibir um DropDownList de produtos pertencentes à categoria selecionada. Para fazer isso, adicione outro DropDownList à página chamada ProductsByCategory
. Assim como acontece com o Categories
DropDownList, crie um novo ObjectDataSource para o ProductsByCategory
DropDownList chamado ProductsByCategoryDataSource
.
Figura 6: Adicionar uma nova fonte de dados para DropDownList ProductsByCategory
(clique para exibir a imagem em tamanho real)
Figura 7: Criar um novo objetoDataSource chamado ProductsByCategoryDataSource
(clique para exibir a imagem em tamanho real)
Como o ProductsByCategory
DropDownList precisa exibir apenas os produtos que pertencem à categoria selecionada, o ObjectDataSource invoca o GetProductsByCategoryID(categoryID)
método do ProductsBLL
objeto .
Figura 8: Escolher usar a ProductsBLL
classe (clique para exibir a imagem em tamanho real)
Figura 9: Configurar o ObjectDataSource para usar o GetProductsByCategoryID(categoryID)
método (clique para exibir a imagem em tamanho real)
Na etapa final do assistente, precisamos especificar o valor do categoryID
parâmetro . Atribua esse parâmetro ao item selecionado do Categories
DropDownList.
Figura 10: efetuar pull do categoryID
valor do parâmetro de Categories
DropDownList (clique para exibir a imagem em tamanho real)
Com o ObjectDataSource configurado, tudo o que resta é especificar quais campos de fonte de dados são usados para a exibição e o valor dos itens do DropDownList. Exiba o ProductName
campo e use o ProductID
campo como o valor.
Figura 11: Especificar os campos de fonte de dados usados para as propriedades e Value
do ListItem
Text
DropDownList (clique para exibir a imagem em tamanho real)
Com ObjectDataSource e ProductsByCategory
DropDownList configurados, nossa página exibirá duas DropDownLists: a primeira listará todas as categorias, enquanto a segunda listará os produtos pertencentes à categoria selecionada. Quando o usuário seleciona uma nova categoria no primeiro DropDownList, um postback será exibido e o segundo DropDownList será recuperado, mostrando os produtos que pertencem à categoria recém-selecionada. Os números 12 e 13 são mostrados MasterDetailsDetails.aspx
em ação quando exibidos por meio de um navegador.
Figura 12: Ao visitar a página pela primeira vez, a categoria bebidas é selecionada (clique para exibir a imagem em tamanho real)
Figura 13: Escolher uma categoria diferente exibe os produtos da nova categoria (clique para exibir a imagem em tamanho real)
Atualmente, o productsByCategory
DropDownList, quando alterado, não causa um postback. No entanto, queremos que um postback ocorra depois que adicionarmos um DetailsView para exibir os detalhes do produto selecionado (Etapa 3). Portanto, marcar caixa de seleção Habilitar AutoPostBack da productsByCategory
marca inteligente do DropDownList.
Figura 14: Habilitar o recurso AutoPostBack para DropDownList productsByCategory
(clique para exibir a imagem em tamanho real)
Etapa 3: Usando uma DetailsView para exibir detalhes do produto selecionado
A etapa final é exibir os detalhes do produto selecionado em um DetailsView. Para fazer isso, adicione um DetailsView à página, defina sua ID
propriedade ProductDetails
como e crie um novo ObjectDataSource para ela. Configure este ObjectDataSource para extrair seus dados do ProductsBLL
método da GetProductByProductID(productID)
classe usando o valor selecionado de ProductsByCategory
DropDownList para o valor do productID
parâmetro .
Figura 15: Escolher usar a ProductsBLL
classe (clique para exibir a imagem em tamanho real)
Figura 16: Configurar o ObjectDataSource para usar o GetProductByProductID(productID)
método (clique para exibir a imagem em tamanho real)
Figura 17: efetuar pull do productID
valor do parâmetro de ProductsByCategory
DropDownList (clique para exibir a imagem em tamanho real)
Você pode optar por exibir qualquer um dos campos disponíveis no ProductDetails
DetailsView. Optei por remover os ProductID
campos , SupplierID
e e CategoryID
reordenei e formatei os campos restantes. Além disso, limpei as propriedades e Width
do Height
DetailsView, permitindo que o DetailsView se expanda para a largura necessária para exibir melhor seus dados em vez de restringi-los a um tamanho especificado. A marcação completa aparece abaixo:
<asp:DetailsView ID="ProductDetails" runat="server"
AutoGenerateRows="False" DataKeyNames="ProductID"
DataSourceID="ObjectDataSource1" 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"
DataFormatString="{0:c}" HeaderText="Price"
HtmlEncode="False" SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitsInStock"
HeaderText="UnitsInStock"
SortExpression="Units In Stock" />
<asp:BoundField DataField="UnitsOnOrder"
HeaderText="UnitsOnOrder"
SortExpression="Units On Order" />
<asp:BoundField DataField="ReorderLevel"
HeaderText="ReorderLevel" SortExpression="Reorder Level" />
<asp:CheckBoxField DataField="Discontinued"
HeaderText="Discontinued" SortExpression="Discontinued" />
</Fields>
</asp:DetailsView>
Reserve um momento para experimentar a MasterDetailsDetails.aspx
página em um navegador. À primeira vista, pode parecer que tudo está funcionando como desejado, mas há um problema sutil. Quando você escolhe uma nova categoria, o ProductsByCategory
DropDownList é atualizado para incluir esses produtos para a categoria selecionada, mas o ProductDetails
DetailsView continuou a mostrar as informações anteriores do produto. O DetailsView é atualizado ao escolher um produto diferente para a categoria selecionada. Além disso, se você testar completamente o suficiente, descobrirá que, se você escolher continuamente novas categorias (como escolher Bebidas no Categories
DropDownList, Condiments e Confeitarias), todas as outras seleções de categorias farão com que o ProductDetails
DetailsView seja atualizado.
Para ajudar a concretizar esse problema, vamos examinar um exemplo específico. Quando você visita a página pela primeira vez, a categoria Bebidas é selecionada e os produtos relacionados são carregados no ProductsByCategory
DropDownList. Chai é o produto selecionado e seus detalhes são exibidos no ProductDetails
DetailsView, conforme mostrado na Figura 18.
Figura 18: Os detalhes do produto selecionado são exibidos em um DetailsView (clique para exibir a imagem em tamanho real)
Se você alterar a seleção de categoria de Bebidas para Condimentos, ocorrerá um postback e o ProductsByCategory
DropDownList será atualizado de acordo, mas o DetailsView ainda exibirá detalhes para Chai.
Figura 19: Os detalhes do produto selecionado anteriormente ainda são exibidos (clique para exibir a imagem em tamanho real)
Escolher um novo produto na lista atualiza o DetailsView conforme o esperado. Se você escolher uma nova categoria depois de alterar o produto, o DetailsView novamente não será atualizado. No entanto, se, em vez de escolher um novo produto, você selecionou uma nova categoria, o DetailsView será atualizado. O que está acontecendo aqui?
O problema é um problema de tempo no ciclo de vida da página. Sempre que uma página é solicitada, ela prossegue por várias etapas como sua renderização. Em uma dessas etapas, os controles ObjectDataSource marcar para ver se algum de seus SelectParameters
valores foi alterado. Nesse caso, o controle da Web de dados associado ao ObjectDataSource sabe que precisa atualizar sua exibição. Por exemplo, quando uma nova categoria é selecionada, o ProductsByCategoryDataSource
ObjectDataSource detecta que seus valores de parâmetro foram alterados e o ProductsByCategory
DropDownList se reassocia, obtendo os produtos para a categoria selecionada.
O problema que surge nessa situação é que o ponto no ciclo de vida da página que o ObjectDataSources marcar para parâmetros alterados ocorre antes da rea vinculação dos controles da Web de dados associados. Portanto, ao selecionar uma nova categoria, ObjectDataSource ProductsByCategoryDataSource
detecta uma alteração no valor de seu parâmetro. O ObjectDataSource usado pelo ProductDetails
DetailsView, no entanto, não observa essas alterações porque o ProductsByCategory
DropDownList ainda não foi recuperado. Posteriormente no ciclo de vida, o ProductsByCategory
DropDownList se associa novamente ao ObjectDataSource, agarrando os produtos para a categoria recém-selecionada. Embora o ProductsByCategory
valor de DropDownList tenha sido alterado, ObjectDataSource ProductDetails
do DetailsView já fez seu valor de parâmetro marcar; portanto, o DetailsView exibe seus resultados anteriores. Essa interação é descrita na Figura 20.
Figura 20: o ProductsByCategory
valor DropDownList é alterado após o ProductDetails
ObjetoDataSource do DetailsView verificar se há alterações (clique para exibir a imagem em tamanho real)
Para corrigir isso, precisamos reassociar explicitamente o ProductDetails
DetailsView depois que o ProductsByCategory
DropDownList tiver sido associado. Podemos fazer isso chamando o ProductDetails
método DetailsView DataBind()
quando o ProductsByCategory
evento dropDownList DataBound
é acionado. Adicione o seguinte código de manipulador de eventos à MasterDetailsDetails.aspx
classe code-behind da página (consulte "Configurando programaticamente os valores de parâmetro do ObjectDataSource" para uma discussão sobre como adicionar um manipulador de eventos):
Protected Sub ProductsByCategory_DataBound(sender As Object, e As EventArgs) _
Handles ProductsByCategory.DataBound
ProductDetails.DataBind()
End Sub
Depois que essa chamada explícita para o ProductDetails
método DetailsView DataBind()
tiver sido adicionada, o tutorial funcionará conforme o esperado. A Figura 21 destaca como essa alteração resolveu nosso problema anterior.
Figura 21: O ProductDetails
DetailsView é atualizado explicitamente quando o ProductsByCategory
evento dropDownList DataBound
é acionado (clique para exibir a imagem em tamanho real)
Resumo
O DropDownList serve como um elemento de interface do usuário ideal para relatórios de master/detalhes em que há uma relação um-para-muitos entre o master e registros de detalhes. No tutorial anterior, vimos como usar um único DropDownList para filtrar os produtos exibidos pela categoria selecionada. Neste tutorial, substituímos o GridView de produtos por um DropDownList e usamos um DetailsView para exibir os detalhes do produto selecionado. Os conceitos discutidos neste tutorial podem ser facilmente estendidos para modelos de dados que envolvem várias relações um-para-muitos, como clientes, pedidos e itens de pedido. Em geral, você sempre pode adicionar um DropDownList para cada uma das entidades "um" nas relações um para muitos.
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 Hilton Giesenow. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, solte-me uma linha em mitchell@4GuysFromRolla.com.