Сегодня мы рассмотрим элемент управления 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.
Увеличить
Аналогично для Windows:
Макет Список (ListLayout)
Увеличить
Макет Сетка (GridLayout)
Увеличить
Макет Ячейка (Макет CellSpanningLayout)
Увеличить
Стилизация элемента управления ListView
Дизайн элемента управления ListView очень легко менять. Для того, чтобы стилизовать элемент управления ListView, можно:
- Использовать WinJS.Binding.Template для описания шаблона отдельного элемента
- Описать CSS стили для элементов ListView, к примеру:
- win-listview задает стиль всего объекта ListView
- win-viewport задает стиль окна просмотра. Здесь при необходимости отображается полоса прокрутки
- win-surface задает стиль прокручиваемой области ListView. Если окно просмотра меньше прокручиваемой области, в нем появляются полосы прокрутки
Увеличить
С полным списком классов можно ознакомиться на ListView reference page.
Например, можно добавить фоновое изображение и рамку для элемента ListView:
#myListView .win-listview {
background-image: url('../images/icecream.png');
border: 2px solid red;
}
Увеличить
Отлично! Мы познакомились с элементом управления 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,
itemsReorderable: true,
layout: { type: WinJS.UI.GridLayout }
}">
</div>
Программное задание возможности переупорядочивания элементов
(function () {
// Получаем ссылку на элемент управления ListView
var listView =
document.querySelector('#listView').winControl;
// Присваиваем значение для itemsReorderable
listView.itemsReorderable = true;
})();
Увеличить
Задачу работы со списком мы решили – теперь мы можем вручную переупорядочить элементы. А что же делать, если мы хотим каким-то образом сгруппировать их? Например, распределить их по группам, в зависимости от первой буквы названия элемента.
Группировка элементов в 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 предусмотрен элемент управления 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>
Увеличить
Важно! Не забудьте определить собственные стили для общего представления.
Увеличить
С тем, какие возможности можно реализовать внутри одного списка в элементе управления 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);
}
});
}
});
})();
Таким образом мы реализовали функцию перетаскивания элемента из одного списка в любое место другого списка. На скриншоте переносимый элемент выделен красным.
Увеличить
Итоги
Итак, мы познакомились с элементом управления 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 можно здесь