Compartilhar via


Filtragem mestre/detalhe em duas páginas usando um controle de repetidor e uma lista de dados (VB)

por Scott Mitchell

Baixar PDF

Neste tutorial, analisamos como separar um relatório de master/detalhes em duas páginas. Na página "master", usamos um controle Repeater para renderizar uma lista de categorias que, quando clicadas, levarão o usuário à página "detalhes", em que uma DataList de duas colunas mostra esses produtos pertencentes à categoria selecionada.

Introdução

No tutorial Filtragem Mestre/Detalhes entre Duas Páginas , examinamos esse padrão usando um GridView para exibir todos os fornecedores no sistema. Este GridView incluiu um HyperLinkField, que foi renderizado como um link para uma segunda página, passando o SupplierID na querystring. A segunda página usou um GridView para listar os produtos fornecidos pelo fornecedor selecionado.

Esses relatórios de master/detalhes de duas páginas também podem ser realizados usando controles DataList e Repeater. A única diferença é que nem o DataList nem o Repeater dão suporte para o controle HyperLinkField. Em vez disso, devemos adicionar um controle Web HyperLink ou um elemento HTML de âncora (<a>) dentro do ItemTemplatecontrole . A propriedade do NavigateUrl HyperLink ou o atributo da href âncora podem ser personalizados usando abordagens declarativas ou programáticas.

Neste tutorial, exploraremos um exemplo que lista as categorias em uma lista com marcadores em uma página usando um controle Repeater. Cada item de lista incluirá o nome e a descrição da categoria, com o nome da categoria exibido como um link para uma segunda página. Clicar neste link levará o usuário para a segunda página, em que um DataList mostrará os produtos que pertencem à categoria selecionada.

Etapa 1: Exibindo as categorias em uma lista com marcadores

A primeira etapa na criação de qualquer relatório de master/detalhes é iniciar exibindo os registros "master". Portanto, nossa primeira tarefa é exibir as categorias na página "master". Abra a CategoryListMaster.aspx página na DataListRepeaterFiltering pasta, adicione um controle Repeater e, na marca inteligente, opte por adicionar um novo ObjectDataSource. Configure o novo ObjectDataSource para que ele acesse seus dados do CategoriesBLL método da GetCategories classe (consulte a Figura 1).

Configurar o ObjectDataSource para usar o método GetCategories da classe CategoriesBLL

Figura 1: configurar o ObjectDataSource para usar o CategoriesBLL método da GetCategories classe (clique para exibir a imagem em tamanho real)

Em seguida, defina os modelos do Repetidor de modo que ele exiba cada nome de categoria e descrição como um item em uma lista com marcadores. Ainda não vamos nos preocupar em ter cada link de categoria para a página de detalhes. O seguinte mostra a marcação declarativa para o Repeater e ObjectDataSource:

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1"
    EnableViewState="False">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
 
    <ItemTemplate>
        <li><%# Eval("CategoryName") %> - <%# Eval("Description") %></li>
    </ItemTemplate>
 
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>
 
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

Com essa marcação concluída, reserve um momento para exibir nosso progresso por meio de um navegador. Como mostra a Figura 2, o Repetidor é renderizado como uma lista com marcadores mostrando o nome e a descrição de cada categoria.

Cada categoria é exibida como um item de lista com marcadores

Figura 2: cada categoria é exibida como um item de lista com marcadores (clique para exibir a imagem em tamanho real)

Para permitir que um usuário exiba as informações de "detalhes" de uma determinada categoria, precisamos adicionar um link a cada item de lista com marcadores que, quando clicado, levará o usuário para a segunda página (ProductsForCategoryDetails.aspx). Esta segunda página exibirá os produtos para a categoria selecionada usando uma DataList. Para determinar a categoria cujo link foi clicado, precisamos passar a categoria CategoryID clicada para a segunda página por meio de algum mecanismo. A maneira mais simples e simples de transferir dados escalares de uma página para outra é por meio da querystring, que é a opção que usaremos neste tutorial. Em particular, a ProductsForCategoryDetails.aspx página espera que o valor selecionado categoryID seja passado por meio de um campo querystring chamado CategoryID. Por exemplo, para exibir os produtos para a categoria Bebidas, que tem um CategoryID de 1, um usuário visitaria ProductsForCategoryDetails.aspx?CategoryID=1.

Para criar um hiperlink para cada item de lista com marcadores no Repetidor, precisamos adicionar um controle Web HyperLink ou um elemento de âncora HTML (<a>) ao ItemTemplate. Em cenários em que o hiperlink é exibido da mesma forma para cada linha, qualquer abordagem será suficiente. Para Repeaters, prefiro usar o elemento anchor. Para usar o elemento de âncora, atualize o ItemTemplate do Repetidor para:

<li>
    <a href='ProductsForCategoryDetails.aspx?CategoryID=<%# Eval("CategoryID") %>'>
        <%# Eval("CategoryName") %>
    </a> - <%# Eval("Description") %>
</li>

Observe que o CategoryID pode ser injetado diretamente dentro do atributo do href elemento de âncora; no entanto, para fazer isso, certifique-se de delimitar o href valor do atributo com apóstrofos (e aspas de anotação), uma vez que o Eval método dentro do href atributo delimita sua cadeia de caracteres ("CategoryID") com aspas. Como alternativa, um controle Da Web do HyperLink pode ser usado em vez disso:

<li>
    <asp:HyperLink runat="server" Text='<%# Eval("CategoryName") %>'
        NavigateUrl='<%# "ProductsForCategoryDetails.aspx?CategoryID=" &
            Eval("CategoryID") %>'>
    </asp:HyperLink>
    - <%# Eval("Description") %>
</li>

Observe como a parte estática da URL — ProductsForCategoryDetails.aspx?CategoryID — é acrescentada ao resultado de diretamente dentro da sintaxe de vinculação de Eval("CategoryID") dados usando a concatenação de cadeia de caracteres.

Uma vantagem de usar o controle HyperLink é que ele pode ser acessado programaticamente do manipulador de eventos do ItemDataBound Repetidor, se necessário. Por exemplo, talvez você queira exibir o nome da categoria como texto e não como um link para categorias sem produtos associados. Esse marcar poderia ser executado programaticamente no ItemDataBound manipulador de eventos; para categorias sem produtos associados, a propriedade do NavigateUrl HyperLink poderia ser definida como uma cadeia de caracteres em branco, resultando, assim, nessa renderização de nome de categoria específica como texto sem formatação (em vez de como um link). Consulte o tutorial Formatação do DataList e do Repetidor baseado em dados para obter mais informações sobre como formatar o conteúdo de DataList e Repeater com base na lógica programática por meio do ItemDataBound manipulador de eventos.

Se você estiver acompanhando, fique à vontade para usar o elemento de âncora ou a abordagem de controle HyperLink em sua página. Independentemente da abordagem, ao exibir a página por meio de um navegador, cada nome de categoria deve ser renderizado como um link para ProductsForCategoryDetails.aspx, passando o valor aplicável CategoryID (consulte Figura 3).

Os nomes de categoria agora vinculam a ProductsForCategoryDetails.aspx

Figura 3: o link Nomes de Categoria agora para ProductsForCategoryDetails.aspx (Clique para exibir a imagem em tamanho real)

Etapa 3: Listando os produtos que pertencem à categoria selecionada

Com a CategoryListMaster.aspx página concluída, estamos prontos para voltar nossa atenção para implementar a página ProductsForCategoryDetails.aspx"detalhes", . Abra esta página, arraste um DataList da Caixa de Ferramentas para o Designer e defina sua ID propriedade como ProductsInCategory. Em seguida, na marca inteligente do DataList, escolha adicionar um novo ObjectDataSource à página, nomeando-o ProductsInCategoryDataSourcecomo . Configure-o de modo que ele chame o ProductsBLL método da GetProductsByCategoryID(categoryID) classe; defina as listas suspensas nas guias INSERT, UPDATE e DELETE como (Nenhum).

Configurar o ObjectDataSource para usar o método GetProductsByCategoryID(categoryID) da classe ProductsBLL

Figura 4: configurar o ObjectDataSource para usar o ProductsBLL método da GetProductsByCategoryID(categoryID) classe (clique para exibir a imagem em tamanho real)

Como o GetProductsByCategoryID(categoryID) método aceita um parâmetro de entrada (categoryID), o assistente Escolher Fonte de Dados nos oferece uma oportunidade de especificar a origem do parâmetro. Defina a origem do parâmetro como QueryString usando o QueryStringField CategoryID.

Usar o campo de querystring CategoryID como a origem do parâmetro

Figura 5: usar o campo CategoryID Querystring como a origem do parâmetro (clique para exibir a imagem em tamanho real)

Como vimos em tutoriais anteriores, depois de concluir o assistente Escolher Fonte de Dados, o Visual Studio cria automaticamente um ItemTemplate para a DataList que lista cada nome e valor do campo de dados. Substitua esse modelo por um que lista apenas o nome, o fornecedor e o preço do produto. Além disso, defina a propriedade datalist RepeatColumns como 2. Após essas alterações, a marcação declarativa de DataList e ObjectDataSource deve ser semelhante à seguinte:

<asp:DataList ID="ProductsInCategory" DataKeyField="ProductID" RepeatColumns="2"
    DataSourceID="ProductsInCategoryDataSource" EnableViewState="False"
    runat="server">
    <ItemTemplate>
        <h5><%# Eval("ProductName") %></h5>
        <p>
            Supplied by <%# Eval("SupplierName") %><br />
            <%# Eval("UnitPrice", "{0:C}") %>
        </p>
    </ItemTemplate>
</asp:DataList>
 
<asp:ObjectDataSource ID="ProductsInCategoryDataSource"
    OldValuesParameterFormatString="original_{0}" runat="server"
    SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
    <SelectParameters>
        <asp:QueryStringParameter Name="categoryID" QueryStringField="CategoryID"
            Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

Para exibir essa página em ação, comece na CategoryListMaster.aspx página; em seguida, clique em um link na lista de categorias com marcadores. Fazer isso levará você para ProductsForCategoryDetails.aspx, passando pelo CategoryID por meio da querystring. O ProductsInCategoryDataSource ObjectDataSource em ProductsForCategoryDetails.aspx obterá apenas esses produtos para a categoria especificada e os exibirá na DataList, que renderiza dois produtos por linha. A Figura 6 mostra uma captura de tela de ProductsForCategoryDetails.aspx ao exibir as Bebidas.

As bebidas são exibidas, duas por linha

Figura 6: As bebidas são exibidas, duas por linha (clique para exibir a imagem em tamanho real)

Etapa 4: Exibindo informações de categoria em ProductsForCategoryDetails.aspx

Quando um usuário clica em uma categoria no CategoryListMaster.aspx, ele é levado para ProductsForCategoryDetails.aspx e mostra os produtos que pertencem à categoria selecionada. No entanto, em ProductsForCategoryDetails.aspx não há nenhuma indicação visual sobre qual categoria foi selecionada. Um usuário que pretendia clicar em Bebidas, mas acidentalmente clicou em Condimentos, não tem como perceber seu erro quando chegar ao ProductsForCategoryDetails.aspx. Para aliviar esse possível problema, podemos exibir informações sobre a categoria selecionada — seu nome e descrição — na parte superior da ProductsForCategoryDetails.aspx página.

Para fazer isso, adicione um FormView acima do controle Repeater em ProductsForCategoryDetails.aspx. Em seguida, adicione um novo ObjectDataSource à página da marca inteligente do FormView chamada CategoryDataSource e configure-o para usar o CategoriesBLL método da GetCategoryByCategoryID(categoryID) classe.

Informações de acesso sobre a categoria por meio do método GetCategoryByCategoryID(categoryID) da classe CategoriesBLL

Figura 7: Informações de acesso sobre a categoria por meio do CategoriesBLL método da GetCategoryByCategoryID(categoryID) classe (clique para exibir a imagem em tamanho real)

Assim como no ProductsInCategoryDataSource ObjectDataSource adicionado na Etapa 3, o CategoryDataSourceassistente Configurar Fonte de Dados nos solicita uma fonte para o GetCategoryByCategoryID(categoryID) parâmetro de entrada do método. Use exatamente as mesmas configurações de antes, definindo a origem do parâmetro como QueryString e o valor QueryStringField como CategoryID (consulte a Figura 5).

Depois de concluir o assistente, o Visual Studio cria automaticamente um ItemTemplate, EditItemTemplatee InsertItemTemplate para o FormView. Como estamos fornecendo uma interface somente leitura, fique à vontade para remover o EditItemTemplate e InsertItemTemplateo . Além disso, fique à vontade para personalizar o FormView.ItemTemplate Depois de remover os modelos supérfluos e personalizar o ItemTemplate, a marcação declarativa de Seu FormView e ObjectDataSource deve ser semelhante à seguinte:

<asp:FormView ID="FormView1" runat="server" DataKeyNames="CategoryID"
    DataSourceID="CategoryDataSource" EnableViewState="False" Width="100%">
    <ItemTemplate>
        <h3>
            <asp:Label ID="CategoryNameLabel" runat="server"
                Text='<%# Bind("CategoryName") %>' />
        </h3>
        <p>
            <asp:Label ID="DescriptionLabel" runat="server"
                Text='<%# Bind("Description") %>' />
        </p>
    </ItemTemplate>
</asp:FormView>
 
<asp:ObjectDataSource ID="CategoryDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategoryByCategoryID" TypeName="CategoriesBLL">
    <SelectParameters>
        <asp:QueryStringParameter Name="categoryID" Type="Int32"
            QueryStringField="CategoryID" />
    </SelectParameters>
</asp:ObjectDataSource>

A Figura 8 mostra uma captura de tela ao exibir esta página por meio de um navegador.

Observação

Além do FormView, também adicionei um controle HyperLink acima do FormView que levará o usuário de volta à lista de categorias (CategoryListMaster.aspx). Fique à vontade para colocar esse link em outro lugar ou omiti-lo completamente.

As informações de categoria agora são exibidas na parte superior da página

Figura 8: As informações de categoria agora são exibidas na parte superior da página (clique para exibir a imagem em tamanho real)

Etapa 5: Exibindo uma mensagem se nenhum produto pertencer à categoria selecionada

A CategoryListMaster.aspx página lista todas as categorias no sistema, independentemente de haver produtos associados. Se um usuário clicar em uma categoria sem produtos associados, a DataList em ProductsForCategoryDetails.aspx não será renderizada, pois sua fonte de dados não terá nenhum item. Como vimos em tutoriais anteriores, o GridView fornece uma EmptyDataText propriedade que pode ser usada para especificar uma mensagem de texto a ser exibida se não houver registros em sua fonte de dados. Infelizmente, nem o DataList nem o Repeater têm essa propriedade.

Para exibir uma mensagem informando ao usuário que não há produtos correspondentes para a categoria selecionada, precisamos adicionar um controle Rótulo à página cuja Text propriedade é atribuída à mensagem a ser exibida caso não haja produtos correspondentes. Em seguida, precisamos definir programaticamente sua Visible propriedade com base em se a DataList contém ou não itens.

Para fazer isso, comece adicionando um Rótulo abaixo de DataList. Defina sua ID propriedade NoProductsMessage como e sua Text propriedade como "Não há produtos para a categoria selecionada..." Em seguida, precisamos definir programaticamente a propriedade desse Visible Rótulo com base em se algum dado foi associado ou não à ProductsInCategory DataList. Essa atribuição deve ser feita depois que os dados tiverem sido associados ao DataList. Para GridView, DetailsView e FormView, poderíamos criar um manipulador de eventos para o evento do controle, que é acionado após a conclusão da DataBound associação de dados. No entanto, nem o DataList nem o Repeater têm um DataBound evento disponível.

Para este exemplo específico, podemos atribuir a propriedade label Visible no Page_Load manipulador de eventos, pois os dados terão sido atribuídos ao DataList antes do evento da Load página. No entanto, essa abordagem não funcionaria no caso geral, pois os dados do ObjectDataSource podem estar associados ao DataList posteriormente no ciclo de vida da página. Por exemplo, se os dados exibidos forem baseados no valor em outro controle, como é ao exibir um relatório de master/detalhes usando um DropDownList para manter os registros "master", os dados poderão não se recuperar para o controle da Web de dados até o PreRender estágio no ciclo de vida da página.

Uma solução que funcionará para todos os casos é atribuir a Visible propriedade ao False manipulador de eventos (ou ItemCreated) do ItemDataBound DataList ao associar um tipo de item de Item ou AlternatingItem. Nesse caso, sabemos que há pelo menos um item de dados na fonte de dados e, portanto, podemos ocultar o NoProductsMessage Rótulo. Além desse manipulador de eventos, também precisamos de um manipulador de eventos para o evento de DataBinding DataList, em que inicializamos a propriedade do Visible Rótulo para True. Como o DataBinding evento é acionado antes dos ItemDataBound eventos, a propriedade do Visible Rótulo será inicialmente definida Truecomo ; se houver itens de dados, no entanto, ela será definida Falsecomo . O código a seguir implementa essa lógica:

Protected Sub ProductsInCategory_DataBinding(sender As Object, e As EventArgs) _
    Handles ProductsInCategory.DataBinding
    'Show the Label
    NoProductsMessage.Visible = True
End Sub
 
Protected Sub ProductsInCategory_ItemDataBound(s As Object, e As DataListItemEventArgs) _
    Handles ProductsInCategory.ItemDataBound
    'If we have a data item, hide the Label
    If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = _
        ListItemType.AlternatingItem Then
 
        NoProductsMessage.Visible = False
    End If
End Sub

Todas as categorias no banco de dados Northwind estão associadas a um ou mais produtos. Para testar esse recurso, ajustei manualmente o banco de dados Northwind para este tutorial, reatribuindo todos os produtos associados à categoria Produce (CategoryID = 7) para a categoria Frutos do Mar (CategoryID = 8). Isso pode ser feito no servidor Explorer escolhendo Nova Consulta e usando a seguinte UPDATE instrução:

UPDATE Products SET
    CategoryID = 8
WHERE CategoryID = 7

Depois de atualizar o banco de dados adequadamente, retorne à CategoryListMaster.aspx página e clique no link Produzir. Como não há mais produtos pertencentes à categoria Produzir, você deverá ver "Não há produtos para a categoria selecionada..." mensagem, conforme mostrado na Figura 9.

Uma mensagem será exibida se não houver produtos pertencentes à categoria selecionada

Figura 9: Uma mensagem será exibida se não houver produtos pertencentes à categoria selecionada (clique para exibir a imagem em tamanho real)

Resumo

Embora master/relatórios detalhados possam exibir os registros de master e detalhes em uma única página, em muitos sites eles são separados em duas páginas da Web. Neste tutorial, analisamos como implementar esse relatório de master/detalhes, tendo as categorias listadas em uma lista com marcadores usando um Repetidor na página da Web "master" e os produtos associados listados na página "detalhes". Cada item de lista na página da Web master continha um link para a página de detalhes que passou o valor da CategoryID linha.

Na página de detalhes, a recuperação desses produtos para o fornecedor especificado foi realizada por meio do ProductsBLL método da GetProductsByCategoryID(categoryID) classe. O categoryID valor do parâmetro foi especificado declarativamente usando o CategoryID valor querystring como a origem do parâmetro. Também examinamos como exibir detalhes da categoria na página de detalhes usando um FormView e como exibir uma mensagem se não houvesse produtos pertencentes à categoria selecionada.

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 a...

Esta série de tutoriais foi revisada por muitos revisores úteis. Os principais revisores deste tutorial foram Zack Jones e Liz Shulok. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, deixe-me uma linha em mitchell@4GuysFromRolla.com.