Como agrupar itens em um ListView (HTML)

[ Este artigo destina-se aos desenvolvedores do Windows 8.x e do Windows Phone 8.x que escrevem aplicativos do Windows Runtime. Se você estiver desenvolvendo para o Windows 10, consulte documentação mais recente ]

Saiba como agrupar itens em um ListView. Para exibir as informações do grupo, como cabeçalhos do grupo e limites do grupo, seu ListView deve usar um layout de grade. Para que o agrupamento funcione totalmente, a propriedade loadingBehavior do controle ListView deve ser definida como "randomaccess" (que é o valor padrão).

O que você precisa saber

Tecnologias

Pré-requisitos

Instruções

Etapa 1: Crie seus dados

O agrupamento exige duas fontes de dados: uma IListDataSource que contém os itens e uma IListDataSource que contém os grupos. Nos itens IListDataSource, cada item contém uma propriedade groupKey que o vincula ao grupo ao qual ele pertence no grupo IListDataSource.

  1. E um novo arquivo JavaScript para o seu projeto que contenha os seus dados. Dê o nome "data.js".

  2. No arquivo data.js que você acabou de criar, crie uma fonte de dados subjacente que fornecerá seu controle ListView com os dados.

    Uma maneira de criar um IListDataSource é criar um WinJS.Binding.List. Cada WinJS.Binding.List tem uma propriedade dataSource que retorna uma IListDataSource que contém os seus dados.

    Este exemplo cria um WinJS.Binding.List de uma matriz de objetos JSON (myData):

    
    // Start of data.js
    (function () {
        "use strict";
    
    
    
        var myData = [
        { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png" },
        { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png" },
        { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png" },
        { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png" },
        { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png" },
        { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png" },
        { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png" },
        { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png" },
        { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" },
        { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" },
        { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" },
        { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" },
        { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png" },
        { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png" },
        { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png" },
        { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png" },
        { title: "Orangy Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Orangy Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Absolutely Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Absolutely Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Triple Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" },
        { title: "Triple Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" },
        { title: "Double Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Double Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Double Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Green Mint", text: "Gelato", picture: "images/60Mint.png" }
        ];
    
        // Create a WinJS.Binding.List from the array. 
        var itemsList = new WinJS.Binding.List(myData);
    

    Observação  Esses dados são referentes a várias imagens. Para obter as imagens, baixe o exemplo de SemanticZoom e agrupamento ListView e copie as imagens do exemplo para seu projeto. Você também pode usar suas próprias imagens —mas não se esqueça de atualizar o valor da propriedade picture em seus dados.

     

    Dica  

    Você não está limitado a usar um WinJS.Binding.List: também pode usar um VirtualizedDataSource personalizado. (StorageDataSource não permite agrupamento.) Para saber mais sobre a criação de uma fonte de dados personalizada, veja Como criar uma fonte de dados personalizada.

     

  3. Crie uma versão da fonte de dados que contém as informações de agrupamento. Se você estiver usando um WinJS.Binding.List, poderá chamar seu método createGrouped para criar uma versão agrupada do List.

    O método createGrouped aceita três parâmetros.

    • getGroupKey: uma função que, dado um item na lista, retorna a chave de grupo à qual pertence o item.
    • getGroupData: uma função que, dado um item na lista, retorna o objeto do dado que representa o grupo ao qual o item pertence.
    • compareGroups: uma função usada para classificar grupos para que o grupo A fique antes do grupo B. A função considera duas chaves de grupos como entrada, compara os dois grupos e retorna um valor menor que zero quando o primeiro grupo é menor que o segundo grupo, igual a zero quando os grupos são iguais, e um valor positivo quando o primeiro grupo é maior que o segundo grupo.

    O método createGrouped retorna uma WinJS.Binding.List que contém duas projeções de dados da lista não agrupada original. As projeções são dinâmicas: se você modifica a lista, modifica o original.

    Este exemplo usa o método List.createGrouped para criar uma versão agrupada do List. Ele usa a primeira letra do título de cada item para definir os grupos.

        // Sorts the groups
        function compareGroups(leftKey, rightKey) {
            return leftKey.charCodeAt(0) - rightKey.charCodeAt(0);
        }
    
        // Returns the group key that an item belongs to
        function getGroupKey(dataItem) {
            return dataItem.title.toUpperCase().charAt(0);
        }
    
        // Returns the title for a group
        function getGroupData(dataItem) {
            return {
                title: dataItem.title.toUpperCase().charAt(0)
            };
        }
    
        // Create the groups for the ListView from the item data and the grouping functions
        var groupedItemsList = itemsList.createGrouped(getGroupKey, getGroupData, compareGroups);
    
  4. Disponibilize os seus dados do escopo global. Dessa forma, quando você cria seu ListView, pode acessar os dados de forma declarativa (mostramos como fazê-lo na Etapa 2.3).

    Este exemplo usa WinJS.Namespace.define para tornar a lista agrupada acessível publicamente.

        WinJS.Namespace.define("myData",
            {
                groupedItemsList: groupedItemsList
            }); 
    
    
    })(); // End of data.js
    

Etapa 2: Crie um ListView que use o layout de grade

Em seguida, crie um ListView e o conecte a seus dados.

  1. Na seção head da página HTML que conterá o ListView, adicione uma referência ao arquivo de dados que você criou na etapa anterior.

    
    
        <!-- Your data file. -->
        <script src="/js/data.js"></script>
    
  2. No body de seu arquivo HTML, crie um ListView. Defina sua propriedade layout como GridLayout.

    
    <div id="groupedListView"
        data-win-control="WinJS.UI.ListView" 
        data-win-options="{layout: {type: WinJS.UI.GridLayout}}"
    ></div>
    
  3. Defina a propriedade itemDataSource do controle ListView como a fonte de dados dos itens agrupados.

    Na Etapa 1, você criou um membro de namespace que contém os itens agrupados que você deseja exibir: myData.groupedItemsList. Chamar esse campo retorna um WinJS.Binding.List. Para obter um IListDataSource que o ListView pode usar, chame a propriedade dataSource: myData.groupedItemsList.dataSource.

    
    <div id="groupedListView"
        data-win-control="WinJS.UI.ListView" 
        data-win-options="{itemDataSource: myData.groupedItemsList.dataSource, 
            layout: {type: WinJS.UI.GridLayout}}"
    ></div>
    
  4. Depois, defina a propriedade groupDataSource do controle ListView como a fonte de dados que contém os dados do grupo. Você pode usar a propriedade groups do objeto List para obter outra List que contém as informações do grupo. Para obter um IListDataSource, chame myData.groupedItemsList.groups.dataSource.

    
    <div id="groupedListView"
        data-win-control="WinJS.UI.ListView" 
        data-win-options="{itemDataSource: myData.groupedItemsList.dataSource, 
            groupDataSource: myData.groupedItemsList.groups.dataSource,
            layout: {type: WinJS.UI.GridLayout}}">
    </div>
    

Execute o aplicativo. Como você não especificou modelos de itens, os dados não estão formatados:

Um ListView mostrando dados brutos de um grupo.

Etapa 3: Crie um modelo de item e um modelo de cabeçalho de grupo

Em sua página HTML, antes de definir seu ListView, crie um WinJS.UI.Template chamado "mediumListIconTextTemplate" e defina a propriedade do controle ListView itemTemplate como o nome desse modelo.


<div id="mediumListIconTextTemplate" 
    data-win-control="WinJS.Binding.Template" 
    style="display: none">
    <div class="mediumListIconTextItem">
        <img class="mediumListIconTextItem-Image" data-win-bind="src: picture" />
        <div class="mediumListIconTextItem-Detail">
            <h4 data-win-bind="innerText: title"></h4>
            <h6 data-win-bind="innerText: text"></h6>
        </div>
    </div>
</div>

<div id="groupedListView"
    data-win-control="WinJS.UI.ListView" 
    data-win-options="{itemDataSource: myData.groupedItemsList.dataSource, 
        itemTemplate: select('#mediumListIconTextTemplate'),
        groupDataSource: myData.groupedItemsList.groups.dataSource,
        layout: {type: WinJS.UI.GridLayout}}">
</div>

Observe que o modelo especifica diversos estilos. Definiremo-os mais tarde.

Execute o aplicativo. Os itens, mas não os cabeçalhos do grupo, estão formatados.

Um ListView mostrando dados brutos de um grupo.

Etapa 4: Crie um modelo de cabeçalho do grupo

Defina um WinJS.UI.Template para o cabeçalho de grupo e dê a ele a ID "headerTemplate". Defina a propriedade groupHeaderTemplate do controle ListView como esse modelo.


<div id="headerTemplate" data-win-control="WinJS.Binding.Template" 
    style="display: none">
    <div class="simpleHeaderItem">
        <h1 data-win-bind="innerText: title"></h1>
    </div>
</div>

<div id="mediumListIconTextTemplate" 
    data-win-control="WinJS.Binding.Template" 
    style="display: none">
    <div class="mediumListIconTextItem">
        <img class="mediumListIconTextItem-Image" data-win-bind="src: picture" />
        <div class="mediumListIconTextItem-Detail">
            <h4 data-win-bind="innerText: title"></h4>
            <h6 data-win-bind="innerText: text"></h6>
        </div>
    </div>
</div>

<div id="groupedListView"
    data-win-control="WinJS.UI.ListView" 
    data-win-options="{itemDataSource: myData.groupedItemsList.dataSource, 
        itemTemplate: select('#mediumListIconTextTemplate'),
        groupDataSource: myData.groupedItemsList.groups.dataSource,
        groupHeaderTemplate: select('#headerTemplate'),
        layout: {type: WinJS.UI.GridLayout}}">
</div>

Execute o aplicativo. Os itens e os cabeçalhos de grupo estão formatados.

Um ListView mostrando dados agrupados.

Etapa 5: Aplique um estilo a seus modelos

Se você deseja especificar de forma mais detalhada a aparência dos itens e cabeçalhos, pode aplicar seus próprios estilos CSS à sua folha de estilos. O CSS desse exemplo aplica estilo aos itens e cabeçalhos, e ao próprio ListView.


/* CSS for the ListView */
#groupedListView
{
    width: 600px;
    height: 300px;
    border: solid 2px rgba(0, 0, 0, 0.13);
}

/* Template for headers */
.simpleHeaderItem
{
    width: 50px;
    height: 50px;
    padding: 8px;
}   

/* Template for items */  
.mediumListIconTextItem
{
    width: 282px;
    height: 70px;
    padding: 5px;
    overflow: hidden;
    display: -ms-grid;
}

    .mediumListIconTextItem img.mediumListIconTextItem-Image 
    {
        width: 60px;
        height: 60px;
        margin: 5px;
        -ms-grid-column: 1;
    }

    .mediumListIconTextItem .mediumListIconTextItem-Detail
    {
        margin: 5px;
        -ms-grid-column: 2;
    }

Quando você executa o aplicativo, os itens são divididos em grupos:

Um ListView com itens agrupados

Você também pode usar as classes de CSS win-groupheader e win-container para definir os estilos de seus grupos e itens. Para saber mais, veja Estilizando a ListView e seus itens.

Comentários

Classificando e filtrando itens e grupos

O WinJS.Binding.List pode classificar e filtrar seus itens e grupos. Para saber mais, veja os métodos createSorted e createFiltered.

Criar uma exibição sem zoom de seus grupos

Agora que você sabe como criar um ListView agrupado, não precisa saber muito mais para usar o controle SemanticZoom para criar uma exibição reduzida de seus grupos.

Exibições reduzida e ampliada de um controle SemanticZoom

Para saber como usar o SemanticZoom, veja Guia de início rápido: adicionando controles SemanticZoom.

Controles ListView agrupados que contêm cabeçalhos interativos

Quando o controle ListView agrupado contém cabeçalhos interativos, nós recomendamos que você dê suporte ao atalho de teclado Ctrl+Alt+G e use-o para mover o usuário para o grupo de navegação atual. Isso deve produzir um comportamento igual a clicar ou tocar no próprio cabeçalho do grupo.

Excluindo grupos e rolando

Quando um grupo é excluído, o ListView pode rolar para um local inesperado, então chame o método ensureVisible para rolar para uma posição que faça sentido para o seu aplicativo.

Exemplo completo

Para ver um exemplo completo mostrando como criar um ListView agrupado, veja o exemplo de Agrupamento de ListView e o SemanticZoom.

Tópicos relacionados

Agrupamento de ListView e SemanticZoom

Guia de início rápido: adicionando controles SemanticZoom