Статьи

Использование вторичных плиток оболочки на Windows Phone с 7.1 SDK

Живые плитки являются одним из ключевых компонентов, характерных для платформы Windows Phone, и позволяют намного быстрее передавать информационные сообщения пользователям приложения. До сих пор одно приложение было привязано к его уникальной Live Tile, которая отображалась только в том случае, если пользователь решил закрепить приложение на домашнем экране. Часто это было не очень эффективно из-за особых ситуаций, когда требовалось более одного живого тайла. Например

  • Приложение погоды, которое отслеживает несколько мест одновременно
  • Фондовое приложение, которое отслеживает несколько индексов
  • Читатель RSS, который отслеживает несколько каналов для обновлений

Вы понимаете, что приложения могут работать с более чем одним экземпляром одного и того же контента, и было бы излишним пытаться включить всю информацию в один Live Tile. В обновленном (7.1) SDK Microsoft представила концепцию независимых плиток оболочки, определенных классом ShellTile .

Посмотрите на этот фрагмент:

ShellTile.Create(new Uri("/MainPage.xaml", UriKind.Relative), new StandardTileData()
{
    BackgroundImage = new Uri("isostore:/Shared/ShellContent/image.png", UriKind.Absolute),
    Title = "Sample"
});

Этот фрагмент кода создает новый ShellTile, который автоматически размещается на главном экране. Как только пользователь коснется его, он перейдет к MainPage.xaml .

ПРИМЕЧАНИЕ . URI, передаваемый на вторичный фрагмент, должен быть относительным. Вы не можете указать абсолютный URI, который будет переходить на определенную веб-страницу, хотя есть обходной путь, о котором я расскажу позже.

Затем я передаю экземпляр StandardTileData , который реализует ShellTileData — базовый класс, который используется для передачи информации о плитке. Я непосредственно устанавливаю заголовок плитки и фоновое изображение. Обратите внимание, что фоновое изображение загружается непосредственно из изолированного хранилища по схеме URI isostore, которую я обсуждал ранее .

ПРИМЕЧАНИЕ. Если изображение, переданное на плитку, не найдено, цвет плитки будет установлен на цвет акцента (темы) ОС.

Есть также некоторые дополнительные свойства, которые вы можете использовать в дополнение к основным:

  • BackContent — используется для отображения строки на обратной стороне плитки. Сам тайл будет автоматически вращаться между базовым и вторичным содержимым.
  • BackTitle — заголовок, который будет отображаться на обратной стороне плитки.
  • Count — количество, отображаемое в углу плитки. Отображается только на лицевой стороне плитки.
  • BackBackgroundImage — фоновое изображение, отображаемое на обратной стороне плитки.

ПРИМЕЧАНИЕ. И BackgroundImage, и BackBackgroundImage могут указывать на внешние ресурсы (изображения вне XAP или изолированного хранилища). Рекомендуется, чтобы эти изображения были достаточно маленькими для быстрой загрузки даже при более медленном интернет-соединении.

Каждый тайл должен иметь уникальный URI, на который он указывает. В противном случае, если URI уже зарегистрирован с другой вторичной плиткой, новая плитка не будет добавлена. Так что же делать, если вы решите, что срок действия одной из плиток истек и ее необходимо заменить?

Во-первых, вам нужно убедиться, что вы можете перечислить плитки, связанные с приложением. Они доступны через ShellTile.ActiveTiles IEnumerable:

foreach (ShellTile tile in ShellTile.ActiveTiles)
{
    Debug.WriteLine(tile.NavigationUri.ToString());
}

Для каждой плитки оболочки вы можете либо обновить ее (и передать новый экземпляр StandardTileData с обновленным содержимым), либо удалить ее. Вы не можете (в данный момент) читать связанные метаданные, кроме URI навигации, который считается уникальным идентификатором для вторичных плиток.

Как правило, дополнительные плитки не должны создаваться без согласия пользователя. Но что, если приложение решит это сделать? Посмотрите на этот фрагмент:

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    for (int i = 0; i < 99; i++)
    {
        ShellTile.Create(new Uri("/MainPage.xaml?" + i.ToString(), UriKind.Relative), new StandardTileData()
        {
            BackgroundImage = new Uri("isostore:/Shared/ShellContent/image.png", UriKind.Absolute),
            Title = "Sample",
            BackContent = "Sample content",
            BackTitle = "BackTitle",
            Count = 10
        });
    }
}

Найдите проблему. Теоретически, это должно работать просто отлично, хотя новые плитки не предоставят никакой дополнительной информации пользователю. Когда приложение инициализируется, цикл активируется, и домашний экран заполняется ненужными плитками. Или это?

Ребята из команды разработчиков Windows Phone предсказали такое поведение, поэтому всякий раз, когда добавляется новая плитка, приложение попадает в состояние надгробия, и пользователь переключается на домашний экран, так что он видит новую живую плитку. Таким образом, приведенный выше код вызовет исключение:

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

Я уже упоминал, что нет способа напрямую вызывать внешние ресурсы через Live Tile — URI навигации должен относиться к самому приложению. Однако вы можете сделать интересный трюк, который позволит плитке перемещаться к веб-ресурсу.

Все, что вам нужно сделать, это указать параметр, который будет содержать веб-адрес:

var n = from c in ShellTile.ActiveTiles
where c.NavigationUri.ToString() == "/MainPage.xaml?uri=http://microsoft.com"
select c;

if (n.Count() == 0)
{
ShellTile.Create(new Uri("/MainPage.xaml?uri=http://microsoft.com", UriKind.Relative), new StandardTileData()
{
Title = "Microsoft Web"
});
}

Внутри кода позади страницы проверьте параметр, когда страница загружена, и, если uri не пустой или нулевой, запустите WebBrowserTask для URI, указанного в параметре:

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    try
    {
        WebBrowserTask task = new WebBrowserTask();
        task.Uri = new Uri(NavigationContext.QueryString["uri"]);
        task.Show();
    }
    catch (KeyNotFoundException ex)
    { MessageBox.Show("No URI was passed to the app."); }
}

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