WinJS + универсальные приложения. Изучаем ListView

в 9:54, , рубрики: Drop, ListView, Semantic Zoom, universal apps, windows, windows phone, winjs, Блог компании Microsoft, разработка под windows phone

WinJS + универсальные приложения. Изучаем ListView - 1

В предыдущей статье я рассказала о том, как создавать галерею изображений при помощи элемента управления FlipView. Сегодня мы рассмотрим элемент управления ListView, который позволяет не только отображать различные данные в виде списка, но и работать с ними – группировать, перетаскивать и переупорядочивать.

Для начала посмотрим, какие возможности для отображения данных доступны в элементе управления ListView. Если вы не знакомы с библиотекой WinJS, то можете почитать об элементах управления, входящих в библиотеку здесь.

Отображение и связывание данных в элементе управления ListView

Для того, чтобы добавить ListView, добавьте на страницу блок div с атрибутом «data-win-control», и присвойте ему значение WinJS.UI.ListView.

<div id="myListView" data-win-control="WinJS.UI.ListView"></div>

Для работы с ListView вам необходимо:

  • Добавить источники данных
  • Задать шаблон для отображения данных
  • Определить макеты для отображения данных

Добавление источника данных

Для того, чтобы подготовить данные для добавления в элемент управления ListView, создайте массив:

(function () {
    "use strict";

    var myData = [
    { title: "Basic banana", text: "Low-fat frozen yogurt", picture: "images/60banana.png" },
    { title: "Banana blast", text: "Ice cream", picture: "images/60banana.png" },
    { title: "Brilliant banana", text: "Frozen custard", picture: "images/60banana.png" },
  ...
    ];

})();

Каждый из объектов имеет три свойства: заголовок, текст и изображение. В данном примере изображения хранятся локально. Составим из нашего массива объектов список Binding.List:

var dataList = new WinJS.Binding.List(myData);

Чтобы список был доступен глобально (это требуется для декларативного описания), не забываем создать пространство имен (в данном случае DataExample), которое предоставляет открытый элемент itemList, возвращающий список. Используя функцию WinJS.Namespace.define:

 var publicMembers =
        {
            itemList: dataList 
        };
WinJS.Namespace.define("DataExample", publicMembers);

Функция WinJS.Namespace.define принимает два параметра: имя создаваемого пространства имен и объект, содержащий одну или несколько пар свойство-значение. Каждое свойство — это открытое имя элемента, а каждое значение — это базовая переменная, свойство или функция в вашем частном коде, к которым вы хотите открыть доступ.

Для того, чтобы добавить созданный список в элемент управления ListView, необходимо присвоить атрибуту «itemDataSource» значение DataExample.itemList.dataSource.

Не забудьте создать шаблон для отображения данных. О том, как создавать шаблон, вы можете почитать здесь.

На заметку: Для того, чтобы применить шаблон элемента, используйте синтаксис select для задания свойства itemTemplate вашему шаблону элемента объекта ListView.
Помимо шаблона для каждого объекта в отдельности, вам необходимо определить один из доступных макетов шаблона для отображения данных элемента управления ListView.

Стандартные макеты для отображения данных элемента управления ListView

У элемента ListView есть три стандартных макета для отображения данных — список, сетка и ячейка. Чтобы использовать один из макетов, добавьте для свойства layout значение WinJS.UI.ListLayout, WinJS.UI.GridLayout< или WinJS.UI.CellSpanningLayout. Макеты WinJS.UI.ListLayout WinJS.UI.GridLayout используются для создания списка и сетки элементов, соответственно. Что касается макета WinJS.UI.CellSpanningLayout – он предназначен для того, чтобы создавать сетку с несколькими различными размерами.

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

Обратите внимание: Макет отображения в виде ячейки доступен только для Windows.

WinJS + универсальные приложения. Изучаем ListView - 2
Аналогично для Windows:

Макет Список (ListLayout)

WinJS + универсальные приложения. Изучаем ListView - 3

Макет Сетка (GridLayout)

WinJS + универсальные приложения. Изучаем ListView - 4

Макет Ячейка (Макет CellSpanningLayout)

WinJS + универсальные приложения. Изучаем ListView - 5

Стилизация элемента управления ListView

Дизайн элемента управления ListView очень легко менять. Для того, чтобы стилизовать элемент управления ListView, можно:

  • Использовать WinJS.Binding.Template для описания шаблона отдельного элемента
  • Описать CSS стили для элементов ListView, к примеру:
    • win-listview задает стиль всего объекта ListView
    • win-viewport задает стиль окна просмотра. Здесь при необходимости отображается полоса прокрутки
    • win-surface задает стиль прокручиваемой области ListView. Если окно просмотра меньше прокручиваемой области, в нем появляются полосы прокрутки WinJS + универсальные приложения. Изучаем ListView - 6

С полным списком классов можно ознакомиться на ListView reference page.

Например, можно добавить фоновое изображение и рамку для элемента ListView:

#myListView .win-listview {
    background-image: url('../images/icecream.png'); 
    border: 2px solid red;
}

WinJS + универсальные приложения. Изучаем ListView - 7

Отлично! Мы познакомились с элементом управления ListView, рассмотрели создание и добавление данных, а также посмотрели доступные макеты для отображения. Теперь научимся работать с элементами внутри ListView.

Изменение порядка элементов в списке ListView

Представьте, что у вас есть список данных, которые вы хотите каким-то образом переупорядочить, поменять строки списка местами. Давайте решим эту задачу.

В элементе управления Listview есть свойство itemsReorderable, которое позволяет менять элементы местами. Свойство itemsReorderable принимает два значения: true и false. В случае, если мы хотим разрешить перестановку элементов, присваиваем свойству itemsReorderable значение true.

Обратите внимание: Свойство itemsReorderable недоступно для Windows Phone.

Декларативное задание возможности переупорядочивания элементов

<div id="listView"
            class="win-selectionstylefilled"
            data-win-control="WinJS.UI.ListView"
            data-win-options="{ 
                itemDataSource: myData.dataSource, 
                itemTemplate: smallListIconTextTemplate,
                <B>itemsReorderable: true,</B>
                layout: { type: WinJS.UI.GridLayout } 
            }">
</div>

Программное задание возможности переупорядочивания элементов

(function () {

    // Получаем ссылку на элемент управления ListView
    var listView = 
        document.querySelector('#listView').winControl;

    // Присваиваем значение для itemsReorderable
    listView.itemsReorderable = true;

})();

WinJS + универсальные приложения. Изучаем ListView - 8

Задачу работы со списком мы решили – теперь мы можем вручную переупорядочить элементы. А что же делать, если мы хотим каким-то образом сгруппировать их? Например, распределить их по группам, в зависимости от первой буквы названия элемента.

Группировка элементов в ListView

Рассмотрим пример группировки данных по первой букве названия каждого элемента. Для реализации группировки создайте версию вашего источника данных, которая будет содержать информацию о группировке элементов. Процесс группировки будет следующим: мы сначала отсортируем заголовки групп путем сравнения юникодов начальных букв в строке, а затем приведем заголовки всех групп к одному виду и создадим сами группы.

// Сравнение групп по ключам
    function compareGroups(leftKey, rightKey) {
        return leftKey.charCodeAt(0) - rightKey.charCodeAt(0);
    }
    // Определяем, ключ группы для элемента
    function getGroupKey(dataItem) {
        return dataItem.title.toUpperCase().charAt(0);
    }
    // Возвращаем заголовок для группы
    function getGroupData(dataItem) {
        return {
            title: dataItem.title.toUpperCase().charAt(0)
        };
    }
    // Создаем новые отсортированные группы 
    var groupedItemsList = itemsList.createGrouped(getGroupKey, getGroupData, compareGroups);

WinJS + универсальные приложения. Изучаем ListView - 9

Мы научились распределять элементы по группам. А что же делать, если элементов и групп слишком много и перемещение по списку становится затруднительным? Для этого в библиотеке WinJS предусмотрен элемент управления Semantic Zoom.

Реализуем навигацию в ListView с помощью элемента управления SemanticZoom

Элемент управления SemanticZoom позволяет реализовать переключение между двумя различными представлениями элементов. Одно из этих представлений – непосредственно представление содержимого. Второе позволяет реализовать быструю навигацию между содержимым, например, отображать заголовки групп для быстрого доступа к содержимому каждой группы.

Для того, чтобы добавить элемент управления SemanticZoom, необходимо создать блок div и присвоить атрибуту data-win-control значение WinJS.UI.SemanticZoom.

<div data-win-control="WinJS.UI.SemanticZoom"></div>

Определите три шаблона для объектов ListView: один — для детализированного представления элементов, другой — для заголовков групп в детализированном представлении элементов, а третий — для заголовков групп в общем представлении. Также необходимо добавить 2 элемента управления ListView. Первый будет определять детализированное представление, а второй — общее представление.

Перейдем непосредственно к добавлению элемента управления SemanticZoom. Для этого просто добавьте в блок элемента управления SemanticZoom элементы управления ListView для детализированного и общего представления.

Обратите внимание на:

  • Источники данных (itemDataSource)
  • Шаблоны для отображения данных

<div id="semanticZoomDiv" data-win-control="WinJS.UI.SemanticZoom">   
            
    <!--- Детализированное представление. -->    
    <div id="zoomedInListView"
        data-win-control="WinJS.UI.ListView" 
        data-win-options="{ itemDataSource: myData.groupedItemsList.dataSource, itemTemplate: select('#mediumListIconTextTemplate'), groupHeaderTemplate: select('#headerTemplate'), groupDataSource: myData.groupedItemsList.groups.dataSource, selectionMode: 'none', tapBehavior: 'none', swipeBehavior: 'none' }"
    ></div>

    <!--- Общее представление. -->
    <div id="zoomedOutListView"
        data-win-control="WinJS.UI.ListView"
        data-win-options="{ itemDataSource: myData.groupedItemsList.<B>groups</B>.dataSource, itemTemplate: select('#semanticZoomTemplate'), selectionMode: 'none', tapBehavior: 'invoke', swipeBehavior: 'none' }"
    ></div>

</div>

WinJS + универсальные приложения. Изучаем ListView - 10

Важно! Не забудьте определить собственные стили для общего представления.

WinJS + универсальные приложения. Изучаем ListView - 11

С тем, какие возможности можно реализовать внутри одного списка в элементе управления ListView мы познакомились. Следующий этап – работа с несколькими списками, а именно – перемещение элементов из одного списка в другой.

Поддержка перетаскивания в элементе управления ListView

Представьте ситуацию, когда у вас есть два списка, и вы хотите переместить элементы из одного списка в другой. Для решения этой задачи вы можете воспользоваться операциями перетаскивания, доступными для элемента управления ListView. Эти операции совместимы с функцией перетаскивания в HTML5. Перетаскивание можно выполнять между двумя элементами управления ListView, между ItemContainer и ListView, а также между любым элементом HTML и ListView. Можно позволить пользователю перетаскивать элементы на определенное место в ListView, а также можно управлять тем, куда вставляются перетаскиваемые элементы. Подробнее об обработке событий перетаскивания в HTML5 можно почитать здесь.

Обратите внимание: Перетаскивание элементов недоступно для Windows Phone.
Для того, чтобы разрешить перетаскивание элементов из ListView, обработаем его с помощью специальных событий перетаскивания, которые были добавлены в HTML5. Условно всю обработку перетаскивания элемента можно разбить на два шага:
Сохранение данных перетаскиваемого элемента в начале операции перетаскивания с помощью метода setData.
Извлечение ранее сохраненных данных после того, как перетаскиваемый элемент будет перемещен в принимающий его элемент с помощью метода getData.

Рассмотрим случай, при котором перетаскиваемый элемент добавляется в любое место списка. Обработаем события для перетаскивания элемента.

(function () {
    "use strict";
    var page = WinJS.UI.Pages.define("/html/drag.html", {
        ready: function (element, options) {
            var dragging = false;
// Обработка события начала перетаскивания
            myDragContent.addEventListener("dragstart", function (eventObject) {
                var dragData = { sourceId: myDragContent.id, data: myItemTitle.innerText, imgSrc: myImg.src };
// Сохранение данных перетаскиваемого элемента
                eventObject.dataTransfer.setData("Text", JSON.stringify(dragData));
// Разрешаем перетаскивание элемента
                dragging = true;
            });
// Обработка события конца перетаскивания
            myDragContent.addEventListener("dragend", function (eventObject) {
                dragging = false;
            });
// Обработка события, при котором перетаскиваемый элемент наведен на тот, который может его принять
            listView.addEventListener("itemdragenter", function (eventObject) {
                if (dragging && eventObject.detail.dataTransfer.types.contains("Text")) {
                    eventObject.preventDefault();
                }
            });
// Обработка события перетаскивания
            listView.addEventListener("itemdragdrop", function (eventObject) {
// Извлечение ранее сохраненных данных после перемещения элемента
var dragData = eventObject.detail.dataTransfer && JSON.parse(eventObject.detail.dataTransfer.getData("Text"));
                if (dragData && dragData.sourceId === myDragContent.id) {
                    var newItemData = { title: dragData.data, text: ("Dragged Item"), picture: dragData.imgSrc };
//Удаляем часть массива и добавляем новые элементы, присваиваем индекс добавленному элементу
                    myData.splice(eventObject.detail.insertAfterIndex + 1, 0, newItemData);
                }
            });
        }
    });
})();

Таким образом мы реализовали функцию перетаскивания элемента из одного списка в любое место другого списка. На скриншоте переносимый элемент выделен красным.

WinJS + универсальные приложения. Изучаем ListView - 12

Итоги

Итак, мы познакомились с элементом управления ListView. Он предоставляет вам возможности работы с элементами списка. Мы рассмотрели различные макеты отображения данных, познакомились со способом реализации изменения порядка элементов в списке, а также с группировкой элементов по первой букве названия каждого элемента. На примере работы с двумя списками, мы реализовали возможность перетаскивания элементов из одного списка в другой. В качестве примера работы ListView с другими элементами управления была рассмотрена возможность реализации навигации при помощи элемента управления Semantic Zoom.

Дополнительные ссылки:

Краткое руководство: добавление элемента управления ListView (HTML)
Краткое руководство: добавление элемента управления Semantic Zoom (HTML)
Элементы управления (HTML с JavaScript)
Creating a unique ListView layout using cell-spanning in HTML
MVA курс по мобильной разработке для веб-разработчиков
Скачать Microsoft Visual Studio можно здесь

Автор: a_bogdanova

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js