Передать на печать

Начала Metro-программирования: поиск и его реализация (ч.1)

Очередная статья из цикла о разработке Metro-приложений, что выполняются под управлением платформы Metro, входящей в состав Windows 8, будет посвящена реализации поиска.

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

Внимание!
Перед чтением следует ознакомиться с предыдущими статьями из цикла "Начала Metro-программирования", опубликованными на сайте TheVista.ru ранее. Описанные в них приёмы программирования будут активно здесь использоваться.


1. Введение
Ранее, при разработке традиционных Windows-приложений, программисту приходилось реализовывать средства поиска данных полностью самому. Он писал код, выполняющий сам поиск, создавал элементы интерфейса, предназначенные для задания ключевого слова и запуска процесса поиска, и обеспечивал вывод найдённых данных на экран.

В случае Metro-приложения нам также придётся многое делать самим, а именно, выполнять поиск и выводить его результаты. Однако создавать элементы интерфейса для указания ключевого слова и запуска поиска нам не придётся. Об этом позаботилась сама платформа Metro.

Если навести курсор мыши на правый нижний угол экрана, появится набор так называемых волшебных кнопок. (Пользователи устройств с сенсорными экранами могут вытянуть его пальцем из-за правой границы экрана.) Волшебная кнопка Поиск (Search) как раз позволяет выполнить поиск в любом из установленных в системе Metro-приложении.


Рис. 1. Панель поиска Metro (выполняется поиск в приложении Maps)


После нажатия этой кнопки на экране появляется панель поиска Поиск (Search), показанная на рис. 1. (Автор не смог адекватно перевести на русский используемый в документации Microsoft термин "charm" и назвал этот интерфейсный элемент панелью.) Большую её часть занимает список установленных Metro-приложений, которые позволяют выполнять поиск данных. Нужное приложение в этом списке можно выбрать щелчком мышью или нажатием пальца.

Далее вводим в расположенное над списком поле ввода нужное ключевое слово и либо нажимаем клавишу <Enter>, либо щёлкаем кнопку с изображением лупы, находящуюся в правой части данного поля ввода. Выбранное нами Metro-приложение будет запущено или активизировано и отобразит все данные, удовлетворяющие указанному нами ключевому слову.

Как видим, всё очень просто и удобно. Удобно для пользователей - теперь им не нужно выискивать среди множества элементов управления, составляющих интерфейс приложения, те, что служат для выполнения поиска. Удобно и для разработчиков - им не придётся реализовывать эти элементы самим.

Конечно, поскольку средства поиска предоставляются самой платформой Metro, нам придётся "научить" наше приложение взаимодействовать с ними. Но сделать это чрезвычайно просто, в чём мы скоро убедимся.


2. Как дать Metro-приложению возможность поиска. Контракт поиска
Изначально Metro-приложение не поддерживает поиск данных. Нам придётся явно указать его поддержку.

Сделать это можно в окне параметров приложения. Чтобы открыть его, отыщем в списке панели Обозреватель решений файл package.appxmanifest и дважды щёлкнем на нём. В главном окне Visual Studio будет открыто ещё одно окно документа, в котором будут наглядно, в графическом виде, представлены все параметры проекта.

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

Как только мы укажем для приложения поддержку поиска, в описание его проекта будет добавлена особая структура данных, называемая контрактом поиска. Его можно рассматривать как "договор" между приложением и платформой Metro, согласно которому первое обязуется поддерживать поиск данных, а вторая - включать данное приложение в список, что выводится в панели Поиск.

Теперь осталось только закрыть окно параметров приложения, сохранив все сделанные в нём правки. И можно приступать к собственно реализации поиска.


3. Три сценария активизации выбранного для выполнения поиска приложения
Как только мы выберем приложение, введём ключевое слово и запустим поиск, платформа Metro сделает две вещи. Во-первых, она активизирует выбранное нами приложение и уведомит его, что мы намереваемся выполнить поиск данных. Во-вторых, она передаст ему введённое нами ключевое слово.

Второе из выполняемых платформой действий мы рассмотрим потом. Сейчас же поговорим о первом действии - активизации выбранного приложения.

Здесь можно выделить три случая:

  • Приложение ещё не запущено. В этом случае оно будет запущено и активизировано.
  • Приложение уже запущено, но неактивно. В этом случае оно будет активизировано.
  • Приложение уже запущено и активно. Понятно, что в этом случае никаких дополнительных действий платформа Metro предпринимать не будет.


В разных случаях платформа Metro будет использовать разные способы передачи введённого ключевого слова и уведомления о запуске поиска. Все эти способы мы рассмотрим по порядку.

3.1. Приложение либо ещё не запущено, либо уже запущено, но неактивно
Сначала рассмотрим случаи, когда выбранное пользователем приложение либо ещё не запущено, либо уже запущено, но неактивно. Пожалуй, такие сценарии осуществления поиска будут встречаться чаще всего.

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

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

3.1.1. Активизация Metro-приложения
Код, обрабатывающий активизацию Metro-приложения, формируется самим Visual Studio при создании проекта. Однако этот код у разных версиях данного средства разработки несколько различается. Давайте выясним, какой код формируется наиболее актуальными в данный момент версиями Visual Studio - бета-версией и Release Candidate.

Весь код логики основного интерфейса пишется в файле default.js. Откроем этот файл.

3.1.1.1. Visual Studio Release Candidate
Насчёт с версии Release Candidate как самой "свежей" на данный момент.

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

var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
WinJS.strictProcessing();


Первое выражение присваивает переменной app объект WinJS.Application, представляющий это приложение. Скорее всего, нам потребуется получать доступ к данному экземпляру объекта, а делать это через переменную с коротким именем несравнимо удобнее, чем каждый раз выписывать "WinIS.Application".

Второе выражение присваивает переменной activation пространство имён Windows.ApplicationModel.Activation. Это пространство имён там также, возможно, понадобится, и получать к нему доступ удобнее через переменную с коротким именем.

Третье выражение является служебным и обеспечивает успешную работу метода processAll объекта WinJS.UI. (Данный метод нам уже знаком по предыдущим статьям цикла; он выполняет инициализацию элементов управления Metro.)

Третье выражение нас в данный момент не интересует. А вот первые два - интересуют, и ещё как!

Дело в том, что объекта WinJS.Application (что теперь доступен через переменную app) поддерживает событие activated. Это событие возникает всякий раз, когда приложение активизируется, то есть выносится на экран компьютера и начинает или возобновляет свою работу. Обработчик этого события можно использовать для выполнения ряда задач, в частности, восстановления состояния приложения и выяснения, каким образом было активизировано данное приложение - через список запущенных приложений, появляющийся при наведении курсора мыши в левый верхний угол экрана, или из панели Поиск.

Кстати, об обработчике события activated... Посмотрим на выражение, располагающееся ниже перечисленных ранее. Вот он - лёгок на помине!..

app.onactivated = function (args) { . . . };


В качестве единственного параметра любая функция - обработчик события принимает экземпляр особого объекта, хранящий сведения о возникшем событии. В случае события activated это будет объект CustomEvent, представляющий "расширенные" сведения о событии. В приведённом ранее примере кода этот параметр имеет имя args.

Объект CustomEvent поддерживает свойство detail, хранящее собственно "расширенные" сведения. Если приложение было активизировано из панели Поиск, значением этого свойства будет экземпляр объекта Windows.UI.WebUI.WebUISearchActivatedEventArgs...

...который поддерживает два очень полезных для нас свойства. Сейчас мы их рассмотрим.

Во-первых, свойство kind. Оно хранит элемент перечисления Windows.ApplicationModel.Activation.ActivationKind, обозначающий способ активизации приложения. Так, если приложение было активизировано в процессе обычного запуска, его значением будет элемент с "говорящим" именем launch.

app.onactivated = function (args) {
  if (args.detail.kind === activation.ActivationKind.launch) {
    //Восстанавливаем сохранённое ранее состояние приложения
  }
};

остояние приложения
}
};[/code]
Здесь мы проверяем, было ли приложение активизировано в процессе обычного запуска, и, если это так, выполняем какие-либо манипуляции, скажем, восстанавливаем сохранённое состояние этого приложения. (Это, кстати, наиболее часто выполняемое здесь действие.)

Обратим внимание, как выполнено обращение к перечислению Windows.ApplicationModel.Activation.ActivationKind. Поскольку пространство имён Windows.ApplicationModel.Activation уже сохранено у нас в переменной activation, мы можем записать ображение к этому перечислению короче - activation.ActivationKind.

Кстати, код, выполняющий данную проверку, уже вставлен в обработчик события activated самим Visual Studio. Нам останется только вставить в него выражения, выполняющие нужные нам действия (например, восстанавливающие состояние).

Если же приложение было активизировано через панель Поиск, значением свойства kind будет элемент search перечисления Windows.ApplicationModel.Activation.ActivationKind.

[code]app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
//Восстанавливаем сохранённое ранее состояние приложения
}
if (args.detail.kind === activation.ActivationKind.search) {
//Выполняем поиск данных
}
};[/code]
Здесь мы добавили в приведённый ранее код проверку, было ли приложение активизировано из панели Поиск.

3.1.1.2. Бета-версия Visual Studio
А какой код формирует бета-версия? Если мы собираемся дорабатывать в Visual Studio Release Candidate приложения, изначально созданные в бета-версии данной среды разработки, нам потребуется это знать.

В начале тела анонимной функции, формирующей анонимное пространство имён, будет присутствовать такое выражение:

[code]var app = WinJS.Application;[/code]
Оно нам уже знакомо и присваивает переменной app экземпляр объекта WinJS.Application, представляющий двнное приложение.

А вот выражения, присваивающего переменной activation пространство имён Windows.ApplicationModel.Activation, в этом случае нет. Поэтому, если нам понадобится обращаться к этому пространству имён, нам придётся писать его имя полностью.

Что мы и видим в коде, привязывающем к событию activated приложения обработчик:

[code]app.onactivated = function (eventObject) {
if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
. . .
}
};[/code]
Вдобавок параметр, получаемый функцией-обработчиком, имеет другое имя - eventObject, а не args, как в случае с Release Candidate.

Громоздко, не так ли? А уж если мы добавим сюда код, проверяющий, было ли приложение активизировано из панели Поиск, получится нечто монструозное:

[code]app.onactivated = function (eventObject) {
if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
//Восстанавливаем сохранённое ранее состояние приложения
}
if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.search) {
//Выполняем поиск данных
}
};[/code]
Впрочем, различия эти непринципиальны - основные принципы и используемые инструменты программирования в обоих случаях одни и те же.

Но как реализовать получение введённого ключевого слова?

3.1.2. Получение указанного ключевого слова
Очень просто! Мы уже знаем, что функции - обработчику события activated в качестве единственного параметра передаётся экземпляр объекта CustomEvent, свойство detail которого хранит экземпляр объекта Windows.UI.WebUI.WebUISearchActivatedEventArgs, хранящего, в свою очередь, "расширенные" сведения о событии. В число этих сведений входит и указанная пользователем ключевая строка для поиска.

Получить её мы можем из свойства queryText объекта Windows.UI.WebUI.WebUISearchActivatedEventArgs. Понятно, что ключевое слово представлено в виде строки.

[code]app.onactivated = function (args) {
var keyword = "";
if (args.detail.kind === activation.ActivationKind.launch) {
//Восстанавливаем сохранённое ранее состояние приложения
}
if (args.detail.kind === activation.ActivationKind.search) {
if (args.detail.queryText === "") {
//Ключевое слово не было указано.
//Приводим приложение в состояние по умолчанию.
} else {
//Ключевое слово было указано
keyword = args.detail.queryText;
//Выполняем поиск данных
}
}
};[/code]
Здесь мы сначала проверяем, указал ли пользователь ключевое слово (ведь он может этого и не делать). Если ключевое слово было указано, мы выполняем поиск данных и выводим на экран его результаты; в противном случае приводим приложение в состояние по умолчанию (например, выводим в нём все доступные данные).

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

Панель Поиск представляется экземпляром объекта Windows.ApplicationModel.Search.SearchPane. Получить этот экземпляр объекта можно вызовом не принимающего параметров метода getForCurrentView данного объекта. В качестве результата он вернёт как раз то, что нам нужно.

[code]var oSearchPane = Windows.ApplicationModel.Search.SearchPane.getForCurrentView();[/code]

Объект Windows.ApplicationModel.Search.SearchPane поддерживает событие querysubmitted, возникающее, когда пользователь запускает процесс поиска. Функция-обработчик этого события в качестве единственного параметра принимает экземпляр объекта Windows.ApplicationModel.Search.SearchPaneQuerySubmittedEventArgs, хранящий сведения о возникшем событии. Свойство queryText данного объекта хранит ключевое слово в виде строки.

[code]oSearchPane.addEventListener("querysubmitted", function(args) {
if (args.detail.queryText === "") {
//Ключевое слово не было указано.
//Приводим приложение в состояние по умолчанию.
} else {
//Ключевое слово было указано
keyword = args.queryText;
//Выполняем поиск данных
}
});[/code]
Здесь мы привязываем к событию querysubmitted панели Поиск обработчик, который будет получать введённое ключевое слово и выполнять поиск данных.


Дополнительные материалы


Окончание следует...


dronov_va, TheVista.Ru Team
Август 2012

  Передать на печать





Все права принадлежат © MSInsider.ru и TheVista.ru, 2013
Сайт является источником уникальной информации о семействе операционных систем Windows и других продуктах Microsoft. Перепечатка материалов возможна только с разрешения редакции.
Работает на WMS 1.1 (Страница создана за 0.298 секунд)