Краткое руководство: добавление поиска в приложение (HTML)

[ Эта статья адресована разработчикам приложений среды выполнения Windows для Windows 8.x и Windows Phone 8.x. При разработке приложений для Windows 10 см. раздел последняя документация]

Многие пользователи привыкли для поиска нужной им информации использовать функцию поиска. Например, если приложение воспроизводит файлы мультимедиа, пользователям потребуется возможность поиска определенной композиции или видео. Пользователям кулинарного приложения необходим поиск конкретных рецептов или ингредиентов.

Добавить функцию поиска в приложение нетрудно — нужно лишь спланировать некоторые аспекты. Вот что вам потребуется.

  • Источник данных для поиска. Вам нужен своего рода каталог или перечень элементов, среди которых пользователи смогут выполнять поиск. Чем подробнее этот перечень, тем лучше будут результаты поиска.
  • Элемент управления для ввода запросов поиска. Windows предоставляет элемент управления SearchBox, который может использоваться приложением. SearchBox предусматривает область ввода запросов, кнопку "Поиск" для выполнения поиска и события для обработки поисковых запросов. Этот элемент даже предоставляет некоторые поиска автоматически.
  • Страница для отображения результатов поиска. Microsoft Visual Studio включает шаблон Страница результатов поиска, который создает большую часть кода, необходимого для обработки запросов поиска и отображения результатов.

В этом кратком руководстве описано использование элементов для добавления функции поиска в приложение.

См. эту функцию в действии в нашей серии Функции приложений от А до Я: Пользовательский интерфейс Магазина Windows от А до Я

Необходимые условия

Настройка данных

Когда пользователь вводит поисковый запрос, приложение ищет интересующие пользователя элементы. Данные, которые ищет приложение, могут быть представлены в нескольких формах: в виде XML-файла, данных нотации объектов JavaScript (JSON), базы данных, веб-службы или файлов в файловой системе.

Примеры в этом руководстве используют демонстрационные данные, сгенерированные Visual Studio при создании нового проекта.

Когда вы используете среду Visual Studio для создания нового приложения таблицы, приложения-концентратора или приложения с разделением, она создает файл с именем data.js в папке js вашего приложения. Этот файл содержит стандартные данные, которые вы можете заменить собственными данными. Например, если приложение отправляет один запрос xhr на получение данных RSS или JSON, вы можете включить свой собственный код в data.js. Включив этот код, вы сможете без труда использовать собственные данные, не меняя модель данных, используемую страницей результатов поиска.

Далее приведен пример данных:

function generateSampleData() {
    // . . .
    var sampleGroups = [
        { key: "group1", title: "Group Title: 1", // . . .
        // . . .
    ];

    var sampleItems = [
        { group: sampleGroups[0], title: "Item Title: 1", // . . .
        // . . .
    ];

    return sampleItems;
}

Чтобы сделать эти данные доступными для ваших файлов, в файле data.js определено пространство имен Data, содержащее следующие элементы.

  • items — список WinJS.Binding.List, содержащий элементы данных. Это сгруппированный List.
  • groups — список WinJS.Binding.List, содержащий группы, которым принадлежат элементы данных. (Вы также можете получить группы вызовом items.groups.)
  • getItemReference — извлекает объект, содержащий ключ группы и заголовок указанного элемента.
  • getItemsFromGroup — извлекает объект FilteredListProjection, содержащий элементы, которые принадлежат группе с указанным ключом.
  • resolveGroupReference — извлекает объект, представляющий группу, которая имеет указанный ключ.
  • resolveItemReference — принимает массив, содержащий две строки: ключ группы и заголовок. Этот метод извлекает элемент, имеющий указанный ключ группы и заголовок.

Вы не обязаны использовать это пространство имен или эти элементы для размещения своих данных, но такой подход облегчит использование шаблона Страница результатов поиска.

(Дополнительные сведения о работе с данными, сгенерированными шаблоном, см. в разделе Настройка данных шаблона Visual Studio.)

Добавление страницы результатов поиска

Страница результатов поиска обрабатывает поисковые запросы и отображает результаты. Добавьте такую страницу в свой проект. (Здесь предполагается, что вы создали проект с помощью шаблонов "Приложение-концентратор", "Приложение таблицы" или "Разделенное приложение". )

Hh465238.wedge(ru-ru,WIN.10).gifДобавление элемента "Страница результатов поиска"

  1. В папке проекта pages в окне Обозреватель решений добавьте новую папку с именем search.

  2. Откройте контекстное меню для папки search и выберите команду Добавить > Новый элемент.

  3. В центральной части диалогового окна Добавление нового элемента выберите элемент Страница результатов поиска. Для этого примера оставьте имя по умолчанию searchResults.html, которое отображается в поле Имя.

  4. Нажмите кнопку Добавить.

    Visual Studio добавляет searchResults.html, searchResults.css и searchResults.js в проект в новой папке search.

Добавление элемента "Поле поиска"

У нас еще остались некоторые задачи на странице результатов поиска, но сначала добавим элемент SearchBox в приложение. SearchBox упростит тестирование страницы результатов поиска при ее реализации.

Элемент SearchBox позволяет пользователям вводить запросы. Он также может отображать варианты. Чтобы добавить SearchBox в приложение, просто добавьте на страницу HTML следующую разметку:

<div class="searchBox"
    data-win-control="WinJS.UI.SearchBox"
    data-win-options="{placeholderText: 'Search'}">
</div>

(Вам также нужно будет зарегистрировать событие onquerysubmitted. Мы сделаем это позднее.)

Где следует разместить поле поиска? Поле поиска рекомендуется разместить на каждой странице приложения, чтобы при необходимости пользователи могли легко обратиться к функции поиска. Если в макете приложения мало свободного места, можно расположить поле поиска на верхней панели приложения.

Hh465238.wedge(ru-ru,WIN.10).gifДобавление элемента управления SearchBox на страницу

  1. Добавим элемент SearchBox на одну из страниц вашего приложения. Эти указания будут справедливы для любой страницы, созданной на основе элемента управления Page.

    Обычно оптимальное место для SearchBox — правый верхний угол страницы. Большинство страниц, создаваемых на основе шаблона Visual Studio (например, шаблона Элемент управления страницей), имеют элемент header, который содержит заголовок страницы и кнопку "Назад":

            <header aria-label="Header content" role="banner">
                <button data-win-control="WinJS.UI.BackButton"></button>
                <h1 class="titlearea win-type-ellipsis">
                    <span class="pagetitle"></span>
                </h1>
            </header>
    

    Просто добавьте элемент SearchBox после элемента h1:

            <header aria-label="Header content" role="banner">
                <button data-win-control="WinJS.UI.BackButton"></button>
                <h1 class="titlearea win-type-ellipsis">
                    <span class="pagetitle">Welcome to basicPage</span>
                </h1>
                <div class="searchBox"
                     data-win-control="WinJS.UI.SearchBox"
                     data-win-options="{placeholderText: 'Search'}">
                </div>
            </header>
    
  2. (Рекомендуется) Вам нужно дать пользователям возможность выполнять поиск содержимого в приложении, когда они просто начинают печатать на клавиатуре.

    Множество людей будет использовать клавиатуру для взаимодействия с Windows 8. Выполнение поиска с помощью клавиатуры обеспечивает эффективное взаимодействие с ней и делает поиск в приложении согласованным с начальным экраном.

    Задайте для свойства focusOnKeyboardInput элемента SearchBox значение true, чтобы поле поиска получало текст, когда пользователь вводит его.

                <div class="searchBox"
                     data-win-control="WinJS.UI.SearchBox"
                     data-win-options="{placeholderText: 'Search',
                     focusOnKeyboardInput: true }">
                </div>
    
  3. Таблица стилей default.css, которую создает Visual Studio, дает элементам заголовков макет -ms-grid. Чтобы поместить свой элемент SearchBox в верхний правый угол страницы, просто добавьте в файл каскадных таблиц стилей (CSS) для вашей страницы следующий стиль:

    .searchBox {
        -ms-grid-column: 4;
        margin-top: 57px;
        margin-right: 29px;
    }
    

Hh465238.wedge(ru-ru,WIN.10).gifОбработка события onquerysubmitted

  1. Вполне возможно, что ваше приложение будет иметь несколько элементов управления SearchBox. Определим единый обработчик событий onquerysubmitted, который все они смогут использовать.

    Откройте файл default.js вашего приложения.

  2. Создайте обработчик событий onquerysubmitted с именем "querySubmittedHandler", который принимает один аргумент с именем "args". (Вы можете поместить определение этого метода в любое место внутри анонимной функции, которая окружает существующий код default.js.)

        function querySubmittedHandler(args) {
    
        }
    
  3. Используйте обработчик событий для перехода на новую страницу результатов поиска при помощи вызова WinJS.Navigation.navigate. Свойство args.details содержит объект, предоставляющий информацию о событии, которое потребуется нашей странице результатов поиска, поэтому передайте этот объект при вызове WinJS.Navigation.navigate.

        function querySubmittedHandler(args) {
            WinJS.Navigation.navigate('/pages/search/searchResults.html', args.detail);
        }
    

    Предупреждение  Если вы создали приложение с помощью шаблона Пустое приложение, то, чтобы заработал поиск, вам необходимо добавить в него поддержку навигации. Вы можете разработать поддержку навигации тем же способом, что и в шаблонах приложения таблицы, приложения с разделением и приложения навигации, — добавляя в приложение пользовательский элемент управления PageControlNavigator. Чтобы посмотреть, как этот пользовательский элемент управления обеспечивает поддержку навигации, перейдите к разделу Краткое руководство: использование одностраничной навигации. Если вам удобнее обеспечить поддержку навигации без использования пользовательского элемента управления, вам нужно написать собственный код, который ожидает передачи данных событий навигации и отвечает на них, например WinJS.Navigation.navigated. Пример поддержки навигации без использования такого пользовательского элемента управления, как PageControlNavigator, см. в примере навигации и журнала навигации.

     

  4. Теперь нам нужно опубликовать этот обработчик событий, определив пространство имен и сделав обработчик его членом. Назовем пространство имен "SearchUtils". Нам также нужно воспользоваться методом WinJS.UI.eventHandler, чтобы мы могли настроить обработчик событий декларативно (дополнительные сведения о том, как это работает, см. в разделе Декларативное задание обработчиков событий).

        WinJS.Namespace.define("SearchUtils",
        {
            querySubmittedHandler: WinJS.UI.eventHandler(querySubmittedHandler)
        }
        );
    
  5. Откройте HTML-страницу, содержащую ваш элемент SearchBox. Используйте свойство data-win-options, чтобы задать для события onquerysubmitted значение SampleUtils.querySubmittedHandler.

                <div class="searchBox"
                     data-win-control="WinJS.UI.SearchBox"
                     data-win-options="{placeholderText: 'Search',
                     focusOnKeyboardInput: true,
                     onquerysubmitted: SearchUtils.querySubmittedHandler}">
                </div>
    

Протестируем страницу. Запустите приложение, введите тестовый запрос в поле SearchBox и нажмите клавишу ВВОД. Если вы используете пример данных, сгенерированных Visual Studio, попробуйте ввести "1" в качестве тестового запроса.

Тестовый запрос

Созданный вами обработчик событий onquerysubmitted открывает страницу результатов поиска, передавая введенный запрос.

Результаты тестового запроса

Если вы используете пример данных, вы должны увидеть совпадения по вашему тестовому запросу. Если вы используете свои собственные данные, результатов может не быть. Нам нужно сначала обновить страницу результатов поиска. Мы вернемся к этому на последующих шагах.

Поиск данных

Пора вернуться к странице результатов поиска. Когда ваше приложение открывает страницу результатов поиска, одним из первых оно вызывает метод _handleQuery. Элемент _handleQuery вызывает несколько методов, которые мы должны изменить:

  1. _generateFilters

    Создает список фильтров, которые пользователь может выбирать для фильтрации результатов.

  2. _searchData

    Отыскивает в ваших данных элементы, удовлетворяющие критерию, и сохраняет их в списке List с названием originalResults.

  3. _populateFilterBar

    Отображает фильтры в нашем списке фильтров.

Обновим эти методы, чтобы подстроить их под ваши данные.

Обновление фильтров

Метод _generateFilters создает список фильтров, которые пользователь может выбирать для фильтрации результатов. Метод, сгенерированный на основе шаблона, создает три фильтра: фильтр "Все" для отображения всех результатов, фильтр для отображения элементов из группы 1 и фильтр для отображения всего остального. Давайте заменим созданный на основе шаблона код кодом, который динамически формирует список фильтров. Таким образом, если вы измените пример данных, ваши новые фильтры появятся на странице. Обновим код _generateFilters и создадим два вспомогательных метода. Но сначала нам нужно обновить наш файл data.js так, чтобы мы могли получить доступ к списку групп. Эти группы мы будем использовать для определения фильтров.

Hh465238.wedge(ru-ru,WIN.10).gifОбновление метода _generateFilters

  1. В файле searchResults.js отыщите метод _generateFilters и удалите код, который он содержит.

  2. Инициализируйте массив _filters. (Массив _filters является переменной-членом, определенной страницей результатов поиска.)

    
            _generateFilters: function () {
                this._filters = [];
    
  3. Теперь создадим фильтр. Фильтр — это объект, имеющий три свойства:

    • results — список List отображаемых элементов. Пока зададим для него значение null.
    • text — отображаемый текст для данного фильтра.
    • predicate — функция, принимающая элемент. Если элемент удовлетворяет критериям фильтра (если он должен отображаться при выборе данного фильтра), эта функция возвращает true. В противном случае она возвращает false.

    Сначала создадим фильтр "Все". Фильтр "Все" отображает любые элементы, поэтому его predicate всегда возвращает true.

    
                this._filters.push({ results: null, text: "All", predicate: function (item) { return true; } });
    
  4. Теперь создадим фильтр для каждой группы наших данных. Наши группы хранятся в списке List с именем Data.groups. Используйте метод forEach для обработки поочередно всех групп в списке List. Метод forEach в качестве своего параметра принимает функцию. Эта функция вызывается для каждого элемента в списке. Передадим ей функцию-член с именем _createFiltersForGroups. (Мы создадим функцию на следующем шаге.)

                if (window.Data) {
                    Data.groups.forEach(this._createFiltersForGroups.bind(this));
                }
            },
    
  5. Теперь создадим функцию _createFiltersForGroups.

    1. Создайте функцию-член с именем _createFiltersForGroups, которая принимает три параметра: element, index и array.

              _createFiltersForGroups: function (element, index, array){
      
      
    2. Параметр element содержит наш объект группы. Создайте новый объект фильтра и воспользуйтесь методом push для добавления его в массив _filters. Задайте для свойства results фильтра значение null, для свойства text — значение element.title, а для свойства predicate — функцию с именем _filterPredicate. Вы определите метод _filterPredicate на следующем шаге.

                  this._filters.push(
                      { results: null, text: element.title, predicate: this._filterPredicate.bind(element)}
                      );
              },
      
    3. Создайте функцию-член с именем _filterPredicate, которая принимает один параметр item. Возвратите значение true, если свойство group параметра item совпадает с текущим объектом группы.

              _filterPredicate: function (item) {
      
                  return item.group === this;          
              },
      

Вот полный код для трех созданных нами методов:

        _generateFilters: function () {
            this._filters = [];
            this._filters.push({ results: null, text: "All", predicate: function (item) { return true; } });

            if (window.Data) {
                Data.groups.forEach(this._createFiltersForGroups.bind(this));
            }
        },

        _createFiltersForGroups: function (element, index, array){
            
            this._filters.push(
                { results: null, text: element.title, predicate: this._filterPredicate.bind(element)}
                );
        },

        _filterPredicate: function (item) {

            return item.group === this;          
        },

Запустите приложение и выполните поиск. Вы должны увидеть новые фильтры на панели фильтров.

Обновленный список фильтров

Если вы используете пример данных, сгенерированных на основе шаблона, вы можете заметить, что некоторые группы обрезаны. Вы можете исправить это, сделав несколько изменений в CSS-файле для вашей страницы результатов поиска.

Hh465238.wedge(ru-ru,WIN.10).gifОбновление CSS-файла для страницы результатов поиска

  1. Откройте файл searchResults.css.

  2. Найдите стиль .searchResults section[role=main] и измените значение свойства -ms-grid-rows на "auto 1fr".

    .searchResults section[role=main] {
        /* Define a grid with rows for the filters and results */
        -ms-grid-columns: 1fr;
        -ms-grid-rows: auto 1fr;
        -ms-grid-row: 1;
        -ms-grid-row-span: 2;
        display: -ms-grid;
    }
    
  3. Найдите стиль .searchResults section[role=main] .filterbar и измените значение свойства word-wrap на "normal", задайте для margin-bottom значение "20px".

        .searchResults section[role=main] .filterbar {
            -ms-font-feature-settings: "case" 1;
            -ms-grid-row: 1;
            list-style-type: none;
            margin-left: 60px;
            margin-right: 60px;
            margin-top: 133px;
            max-width: calc(100% - 120px);
            position: relative;
            white-space: normal;
            z-index: 1; 
            margin-bottom: 20px; 
        }
    
  4. Найдите стиль .searchResults section[role=main] .filterbar li и измените значение свойства display на "inline-block".

            .searchResults section[role=main] .filterbar li {
                display: inline-block; 
                margin-left: 20px;
                margin-right: 20px;
                margin-top: 5px;
                opacity: 0.6;
            }
    
  5. Найдите стиль .searchResults section[role=main] .resultslist и измените значение свойства -ms-grid-row на "2", задайте для -ms-grid-row-span значение "1".

        .searchResults section[role=main] .resultslist {
            -ms-grid-row: 2;
            -ms-grid-row-span: 1;
            height: 100%;
            position: relative;
            width: 100%;
            z-index: 0;
        }
    

Запустите приложение и выполните новый поиск. Теперь вы должны увидеть все фильтры.

Обновленный список фильтров

Обновление алгоритма поиска

Метод _searchData отыскивает в данных элементы, удовлетворяющие запросу поиска. Код, сгенерированный на основе шаблона, просматривает заголовки, подзаголовки и описания всех элементов. Напишем свой собственный код поиска, который сортирует результаты по релевантности.

Hh465238.wedge(ru-ru,WIN.10).gifОбновление метода _searchData

  1. В файле searchResults.js найдите метод _searchData и удалите код, который он содержит.

  2. Создайте переменную с именем originalResults. Это будет возвращаемое значение.

            // This function populates a WinJS.Binding.List with search results for the
            // provided query.
            _searchData: function (queryText) {
    
                // Create a variable for the results list.
                var originalResults;
    
  3. Сделаем наш поиск независимым от регистра букв, переведя как текст запроса, так и текст, в котором выполняется поиск, в нижний регистр. Начнем с того, что переведем текст запроса в нижний регистр и сохраним результат в переменной с именем lowercaseQueryText.

                // Convert the query to lowercase. 
                var lowercaseQueryText = queryText.toLocaleLowerCase();
    
  4. Перед тем как обращаться к данным, давайте проверим, существуют ли они.

                if (window.Data)
                {
    
  5. Если вы используете пример данных, представленный в файле data.js, то наши элементы хранятся в Data.items, объект WinJS.Binding.List. Воспользуйтесь методом createFiltered для фильтрации элементов, которые не удовлетворяют запросу поиска.

    Метод createFiltered принимает функцию фильтрации в качестве своего параметра. Функция фильтрации принимает один параметр — item. Список List вызывает эту функцию для каждого элемента в списке, чтобы определить, должен ли он находиться в фильтрованном списке. Функция возвращает значение true, если элемент должен быть включен, и значение false, если он должен быть пропущен.

                    originalResults = Data.items.createFiltered(
    
                        function (item) {
    
  6. В JavaScript вы можете присоединять новые свойства к существующим объектам. Добавьте свойство ranking к элементу item и задайте для него значение "–1".

                            // A ranking < 0 means that a match wasn't found. 
                            item.ranking = -1;
    
  7. Сначала давайте проверим, содержит ли заголовок элемента текст запроса. Если да, дадим элементу 10 очков.

                            if (item.title.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
    
                                item.ranking += 10;
                            }
    
  8. Затем проверим, есть ли совпадения в поле подзаголовка. Если найдем совпадение, дадим элементу 5 очков.

                            if (item.subtitle.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
                                item.ranking += 5;
                            }
    
  9. И, наконец, проверим поле описания. Если найдем совпадение, дадим элементу 1 очко.

                            if (item.description.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
                                item.ranking += 1;
                            }
    
  10. Если элемент имеет ранг –1, это означает, что он не удовлетворяет нашему запросу поиска. Для нашего возвращаемого значения определите true, если элемент имеет ранг 0 и выше.

                            return (item.ranking >= 0);
                        }
                     );
    
  11. Таким образом, мы отфильтровали список, оставив в нем только элементы, удовлетворяющие запросу поиска, и добавили информацию для ранжирования. Теперь давайте воспользуемся методом createSorted для сортировки списка результатов так, чтобы элементы с более высоким рангом располагались выше.

                    // Sort the results by the ranking info we added. 
                    originalResults = originalResults.createSorted(function (firstItem, secondItem){
                            if (firstItem.ranking == secondItem.ranking) {
                                return 0;
                            }
                            else if (firstItem.ranking < secondItem.ranking)
                                return 1;
                            else
                                return -1;
                        });
    
                }
    
  12. Если данных нет, создайте пустой список.

                else {
    
                    // For some reason, the Data namespace is null, so we 
                    // create an empty list to return. 
                    originalResults = new WinJS.Binding.List();
    
                }
    
  13. Наконец, возвратите результаты.

                return originalResults;
            }
    

Ниже приведен полный код обновленного метода _searchData.

        _searchData: function (queryText) {

            // Create a variable for the results list.
            var originalResults;

            // Convert the query to lowercase. 
            var lowercaseQueryText = queryText.toLocaleLowerCase();

            if (window.Data)
            {
                originalResults = Data.items.createFiltered(

                    function (item) {

                        // A ranking < 0 means that a match wasn't found. 
                        item.ranking = -1;

                        if (item.title.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {

                            item.ranking += 10;
                        }
                        if (item.subtitle.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
                            item.ranking += 5;
                        }
                        if (item.description.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
                            item.ranking += 1;
                        }

                        return (item.ranking >= 0);
                    }
                 );

                // Sort the results by the ranking info we added. 
                originalResults = originalResults.createSorted(function (firstItem, secondItem){
                        if (firstItem.ranking == secondItem.ranking) {
                            return 0;
                        }
                        else if (firstItem.ranking < secondItem.ranking)
                            return 1;
                        else
                            return -1;
                    });

            }
            else {

                // For some reason, the Data namespace is null, so we 
                // create an empty list to return. 
                originalResults = new WinJS.Binding.List();

            }

            return originalResults;
        }

Обеспечение перехода к элементам, возвращенным в результате поиска

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

Когда пользователь щелкает элемент в списке ListView, элемент ListView запускает событие oniteminvoked. Код, сгенерированный на основе шаблона, для нашей страницы результатов поиска определяет обработчик событий oniteminvoked с именем _itemInvoked. Обновим код так, что при активации элемента будет выполняться переход к нему.

Hh465238.wedge(ru-ru,WIN.10).gifДобавление возможности перехода к элементам

  • Откройте файл searchResults.js и добавьте в функцию _itemInvoked код для перехода на нужную страницу. Внимание  Показанный здесь универсальный код ресурса (URI) относится к шаблону "Приложение-концентратор". Для шаблона "Приложение таблицы" URI должен быть следующим: /pages/itemDetail/itemDetail.html. Для шаблона "Разделенное приложение" URI должен быть следующим: /pages/items/items.html.

     

            _itemInvoked: function (args) {
                args.detail.itemPromise.done(function itemInvoked(item) {
                    // TODO: Navigate to the item that was invoked.
                    var itemData = [item.groupKey, item.data.title];
                    WinJS.Navigation.navigate("/pages/item/item.html", { item: itemData });
                });
            },
    

(Необязательно) Обновление свойства ItemTemplate элемента управления ListView

Созданная на основе шаблона страница результатов поиска определяет свойство itemTemplate так, чтобы можно было работать с источником демонстрационных данных, которые создает Visual Studio. В каждом элементе данных предполагаются следующие поля: "image", "title", "subtitle" и "description".

Если ваши элементы данных имеют другие поля, вам нужно изменить itemTemplate. Дополнительные сведения см. в разделе Краткое руководство: добавление элемента ListView.

(Необязательно) Добавление вариантов поиска

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

Варианты можно получить из нескольких источников.

  • Вы можете определить их сами. Например, вы можете создать список производителей автомобилей.
  • Вы можете получить их в Windows, если в вашем приложении выполняется поиск в локальных файлах.
  • Вы можете получить их в веб-службе или с сервера.

Рекомендации по взаимодействию с пользователем при отображении вариантов см. в разделе, содержащем руководство и контрольный список для поиска.

Чтобы с помощью пары строк кода добавить варианты, основанные на локальных файлах из Windows, можно воспользоваться LocalContentSuggestionSettings. Кроме того, можно зарегистрировать событие onsuggestionsrequested, запускаемое элементом управления поля поиска, и составить собственный список вариантов на основе предложений, полученных из другого источника (например, локально определенного списка или веб-службы). В этом кратком руководстве показано, как обрабатывать событие onsuggestionsrequested.

Дополнительные примеры кода, демонстрирующие, как добавлять варианты поиска, можно просмотреть, скачав пример элемента управления SearchBox. В этом примере показано, как добавлять варианты поиска из всех трех возможных источников и как добавлять варианты для восточноазиатских языков с помощью альтернативных форм текста запроса, созданных редактором метода ввода (IME). (Рекомендуется использовать альтернативные варианты текста запроса, если приложение предназначено для пользователей из Японии или Китая.)

Hh465238.wedge(ru-ru,WIN.10).gifОбработка события SuggestionsRequested

  1. Вероятно, в приложении будет несколько элементов управления SearchBox. Определим один обработчик событий в файле default.js, который смогут использовать все элементы. Добавьте этот код после метода querySubmittedHandler, созданного на более раннем шаге.

        function suggestionsRequestedHandler(args) {
    
  2. Преобразуйте текст запроса SearchBox в нижний регистр.

            var query = args.detail.queryText.toLocaleLowerCase();
    
  3. Система автоматически предлагает варианты, например из предыдущих поисковых запросов пользователя. Добавим наши варианты поиска к предоставленным системой.

            // Retrieve the system-supplied suggestions.
            var suggestionCollection = args.detail.searchSuggestionCollection;
    
  4. Убедитесь, что текст запроса содержит хотя бы один символ и есть доступ к данным.

            if (query.length > 0 && window.Data) {
    
  5. Проверьте наличие совпадений для всех элементов данных. Если совпадение найдено, добавьте заголовок соответствующего элемента в коллекцию вариантов поиска.

                Data.items.forEach(
                    function (element, index, array) {
                        if (element.title.substr(0, query.length).toLocaleLowerCase() === query) {
                            suggestionCollection.appendQuerySuggestion(element.title);
                        }
    
                    });
    
  6. Свойство args.detail.linguisticDetails.queryTextAlternatives предоставляет дополнительные варианты для пользователей, которые вводят текст в редакторе IME. Применение этих вариантов улучшает взаимодействие с пользователями при поиске на восточноазиатских языках. Проверим альтернативные варианты текста запроса на наличие строк, содержащих исходный запрос, и добавим их в список вариантов.

                args.detail.linguisticDetails.queryTextAlternatives.forEach(
                    function (element, index, array) {
                        if (element.substr(0, query.length).toLocaleLowerCase() === query) {
                            suggestionCollection.appendQuerySuggestion(element);
                        }
    
                    });
            }
        }
    

    Это весь код, необходимый для обработчика событий вариантов поиска. Вот полный код метода suggestionsRequestedHandler:

        function suggestionsRequestedHandler(args) {
    
            var query = args.detail.queryText.toLocaleLowerCase();
    
            // Retrieve the system-supplied suggestions.
            var suggestionCollection = args.detail.searchSuggestionCollection;
    
            if (query.length > 0 && window.Data) {
    
                Data.items.forEach(
                    function (element, index, array) {
                        if (element.title.substr(0, query.length).toLocaleLowerCase() === query) {
                            suggestionCollection.appendQuerySuggestion(element.title);
                        }
    
                    });
    
                args.detail.linguisticDetails.queryTextAlternatives.forEach(
                    function (element, index, array) {
                        if (element.substr(0, query.length).toLocaleLowerCase() === query) {
                            suggestionCollection.appendQuerySuggestion(element);
                        }
    
                    });
    
            }
        }
    

    Примечание  Если источник данных является асинхронным, вы должны обновления коллекции вариантов поиска упаковать в объект Promise. Пример кода использует объект List, который является синхронным источником данных. Вот как будет выглядеть метод, если объект List будет асинхронным источником.

     

        function suggestionsRequestedHandler(args) {
    
            var query = args.detail.queryText.toLocaleLowerCase();
    
            // Retrieve the system-supplied suggestions.
            var suggestionCollection = args.detail.searchSuggestionCollection;
    
            if (query.length > 0 && window.Data) {
    
                args.detail.setPromise(WinJS.Promise.then(null, 
                    function () {
                        Data.items.forEach(
                            function (element, index, array) {
                                if (element.title.substr(0, query.length).toLocaleLowerCase() === query) {
                                    suggestionCollection.appendQuerySuggestion(element.title);
                                }
    
                            });
    
                        args.detail.linguisticDetails.queryTextAlternatives.forEach(
                            function (element, index, array) {
                                if (element.substr(0, query.length).toLocaleLowerCase() === query) {
                                    suggestionCollection.appendQuerySuggestion(element);
                                }
    
                            });
    
                    })
                 );
            }
        }
    
  7. Это весь код, необходимый для обработчика событий вариантов поиска. Сделаем его общедоступным, объявив его с помощью пространства имен SearchUtils, определенного нами на более раннем шаге:

        WinJS.Namespace.define("SearchUtils",
        {
            querySubmittedHandler: WinJS.UI.eventHandler(querySubmittedHandler),
            suggestionsRequestedHandler: WinJS.UI.eventHandler(suggestionsRequestedHandler)
        }
        );
    
  8. Теперь зарегистрируем событие с SearchBox. Откройте HTML-страницу, содержащую элемент SearchBox, и задайте для события onsuggestionsrequested значение SearchUtils.suggestionsRequestedHandler.

                <div class="searchBox"
                     data-win-control="WinJS.UI.SearchBox"
                     data-win-options="{placeholderText: 'Search',
                     focusOnKeyboardInput: true,
                     onquerysubmitted: SearchUtils.querySubmittedHandler,
                     onsuggestionsrequested: SearchUtils.suggestionsRequestedHandler}">
                </div>
    

Реализация контракта "Поиск" (для предыдущих версий Windows)

До выхода Windows 8.1 приложения использовали чудо-кнопку "Поиск" для поиска в приложении. Разработчики реализовывали контракт "Поиск" и использовали API SearchPane для обработки запросов и получения вариантов и результатов.

Контракт "Поиск" и API SearchPane в Windows 8 полностью поддерживаются, однако в Windows 8.1 рекомендуется использовать элемент управления SearchBox вместо SearchPane. В приложениях, использующих SearchBox, нет необходимости реализовывать контракт "Поиск".

Должно ли приложение использовать SearchPane и контракт "Поиск"? Если вы не предполагаете, что пользователи будут часто выполнять поиск в приложении, то можете использовать SearchPane и контракт "Поиск". Рекомендуется использовать в приложении кнопку с панелью навигации (Segoe UI Symbol 0xE0094, 15pt), нажав которую, пользователь сможет активировать панель поиска. Код, реализующий SearchPane и контракт "Поиск", см. в примере контракта "Поиск".

Краткая сводка и дальнейшие действия

Чтобы добавить функцию поиска в приложение, вы использовали элемент управления SearchBox и страницу результатов поиска.

Правила, помогающие разработать и организовать удачное взаимодействие с пользователями при поиске, см. в разделе Руководство и контрольный список для поиска.

Связанные разделы

Образец элемента управления "Поле поиска"

Руководство и контрольный список для поиска