Использование стандартных диалогов в Windows Phone 7
Любое мобильное устройство обладает стандартной функциональностью, которая специфична для конкретной платформы. Если говорить, например, о мобильных устройствах на базе Windows Phone 7, то такая функциональность – это и запуск камеры, и звонок по телефону, и отправка электронной почты с помощью Outlook Mobile, и ряд других задач. Для того, чтобы приложения могли использовать эту функциональность существует стандартный API, которым могут воспользоваться разработчики. О нем здесь и пойдет речь.

Вообще, стандартная функциональность операционной системы доступна приложению путем использования специальных объектов Tasks
(задачи), которые входят в стандартный API. Идеология строится на том, чтобы для каждого сценария иметь свою задачу. Каждая задача представлена в виде стандартного объекта, реализующего интерфейс ITask
или IChooser
.
Интерфейс ITask
очень прост и состоит из единственного метода для запуска задачи.
public interface ITask
{
void Show();
}
Как видно, задачи можно просто запускать, более никакой функциональности недоступно. В некоторых ситуациях этого недостаточно. Например, если мы запускаем камеру, то хотелось бы получить результат. Поэтому для таких задач появился интерфейс IChooser
, который расширяет функциональность ITask
.
public abstract class IChooser : ITask
{
protected IChooser();
public EventArgs EventArgs { get; set; }
public abstract void Deserialize(Stream s);
public abstract void OnInvokeReturned(byte[] outputBuffer);
public abstract void Serialize(Stream s);
public abstract void Show();
}
Здесь одним из наиболее важных моментов является наличие свойства EventArgs
, которое и будет содержать результат выполнения задачи. Особо внимательные читатели уже, наверное, заметили, что на самом деле IChooser
– это вовсе никакой не интерфейс, IChooser
— это абстрактный класс. Это необходимо для того, чтобы в нем можно было реализовать часть логики.
Все задачи в Windows Phone 7 (за маленьким исключением) реализуют тот или иной интерфейс. Поэтому с большинством из них мы можем работать, абстрагируясь от конкретной задачи.
Теперь давайте посмотрим какие типы задач существуют на данный момент в Windows Phone 7 и каким образом их можно использовать. В первую очередь для того, чтобы использовать задачи, следует подключить стандартную сборку Microsoft.Phone.Tasks
.

После подключения этой сборки становятся доступными объекты, выполняющие различные задачи в Windows Phone 7. Типы задач, доступные на момент написания этого материала (April 2010 CTP):
CameraCaptureTask
– позволяет получить изображение с камеры;EmailAddressChooserTask
– позволяет выбрать абонента из телефонной книги и получить его e-mail;EmailComposeTask
– запускает задачу написания e-mail сообщения;MarketplaceLauncher
– запускает приложение для Marketplace;MediaPlayerLauncher
– запускает проигрыватель медиа-файлов;PhoneCallTask
– запускает приложения набора номера телефона;PhoneNumberChooserTask
– позволяет выбрать абонента из телефонной книги и получить его номер телефона;PhotoChooserTask
– позволяет выбрать фото из существующей коллекции изображений или с камеры;SaveEmailAddressTask
– позволяет сохранить адрес электронной почты в телефонной книге;SavePhoneNumberTask
– позволяет сохранить номер телефона в телефонной книге;SearchTask
– запускает системное окно поиска;SmsComposeTask
– запускает задачу написания сообщения SMS;WebBrowserTask
– запускает веб-браузер.
После запуска задачи и ее выполнения в некоторых случаях требуется обработать результаты выполнения задачи. Для этого можно воспользоваться двумя способами – обратиться к экземпляру класса той задачи, которую запустил пользователь и использовать свойство EventArgs
, либо использовать объект ChooserListener
и подписаться на событие ChooserCompleted
для обработки результата. Оба подхода по большей степени равноценны, и какой из них выбрать – дело конкретного случая. Использование объекта ChooserListener
сводится к следующему коду.
public MainPage()
{
InitializeComponent();
SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;
ChooserListener.ChooserCompleted += new EventHandler(ChooserListener_ChooserCompleted);
}
void ChooserListener_ChooserCompleted(object sender, EventArgs e)
{
var data = (TaskEventArgs<PhotoResult>)e;
var photoStream = data.Result.ChosenPhoto;
// обработка изображения
}
Теперь, когда основные принципы работы с задачами в Windows Phone 7 стали более понятны, давайте рассмотрим небольшой пример, как мы по шагам можем вызывать задачи, а также получим изображение с камеры (в случае эмулятора – виртуальной камеры).
Работа с камерой в Windows Phone 7
Создадим новый проект Windows Phone 7 и сделаем ссылку на сборку Microsoft.Phone.Tasks
.В нашем приложении мы будем использовать меню для вызова разных типов задач, поэтому сделаем также ссылку на сборку Microsoft.Phone.Shell
. Добавим пространство имен для Microsoft.Phone.Shell
в разметку формы и создадим объект ApplicationBar
.
<phoneNavigation:PhoneApplicationPage
x:Class="LauncherTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone.Shell"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}">
<phoneNavigation:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsMenuEnabled="True">
<shell:ApplicationBar.MenuItems>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phoneNavigation:PhoneApplicationPage.ApplicationBar>
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitleGrid is the name of the application and page title-->
<Grid x:Name="TitleGrid" Grid.Row="0">
<TextBlock Text="MY APPLICATION" x:Name="textBlockPageTitle" Style="{StaticResource PhoneTextPageTitle1Style}"/>
<TextBlock Text="page title" x:Name="textBlockListTitle" Style="{StaticResource PhoneTextPageTitle2Style}"/>
</Grid>
<!--ContentGrid is empty. Place new content here-->
<Grid x:Name="ContentGrid" Grid.Row="1">
<Image Height="171" HorizontalAlignment="Left" Margin="179,347,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="170" />
</Grid>
</Grid>
</phoneNavigation:PhoneApplicationPage>
Несмотря на то, что основной сценарий в данном приложении – использование мобильной камеры, мы также оставим возможно запускать другие типы задач. Поэтому добавим в меню несколько пунктов для каждого из типов задач.
<phoneNavigation:PhoneApplicationPage
x:Class="LauncherTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone.Shell"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}">
<phoneNavigation:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsMenuEnabled="True">
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text="Camera" Click="CameraMenuItem_Click"/>
<shell:ApplicationBarMenuItem Text="Email address" Click="EmailAddressMenuItem_Click"/>
<shell:ApplicationBarMenuItem Text="Email message" Click="EmailMessageMenuItem_Click"/>
<shell:ApplicationBarMenuItem Text="Marketplace" Click="MarketPlaceMenuItem_Click"/>
<shell:ApplicationBarMenuItem Text="Media player" Click="MediaPlayerMenuItem_Click"/>
<shell:ApplicationBarMenuItem Text="Phone call" Click="PhoneCallMenuItem_Click"/>
<shell:ApplicationBarMenuItem Text="Phone number" Click="PhoneNumberMenuItem_Click"/>
<shell:ApplicationBarMenuItem Text="Choose photo" Click="ChoosePhotoMenuItem_Click"/>
<shell:ApplicationBarMenuItem Text="Save email" Click="SaveEmailMenuItem_Click"/>
<shell:ApplicationBarMenuItem Text="Save phone number" Click="SavePhoneNumberMenuItem_Click"/>
<shell:ApplicationBarMenuItem Text="Search" Click="SearchMenuItem_Click"/>
<shell:ApplicationBarMenuItem Text="Compse SMS" Click="ComposeSMSMenuItem_Click"/>
<shell:ApplicationBarMenuItem Text="Web" Click="WebMenuItem_Click"/>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phoneNavigation:PhoneApplicationPage.ApplicationBar>
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitleGrid is the name of the application and page title-->
<Grid x:Name="TitleGrid" Grid.Row="0">
<TextBlock Text="MY APPLICATION" x:Name="textBlockPageTitle" Style="{StaticResource PhoneTextPageTitle1Style}"/>
<TextBlock Text="page title" x:Name="textBlockListTitle" Style="{StaticResource PhoneTextPageTitle2Style}"/>
</Grid>
<!--ContentGrid is empty. Place new content here-->
<Grid x:Name="ContentGrid" Grid.Row="1">
<Image Height="171" HorizontalAlignment="Left" Margin="179,347,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="170" />
</Grid>
</Grid>
</phoneNavigation:PhoneApplicationPage>
Обработчик для каждого из пунктов меню будет иметь достаточно простой вид – он будет создавать соответствующий тип задачи и запускать его.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Tasks;
using System.Windows.Media.Imaging;
namespace LauncherTest
{
public partial class MainPage : PhoneApplicationPage
{
private CameraCaptureTask _task = new CameraCaptureTask();
public MainPage()
{
InitializeComponent();
SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;
}
private void CameraMenuItem_Click(object sender, EventArgs e)
{
(new CameraCaptureTask()).Show();
}
private void EmailAddressMenuItem_Click(object sender, EventArgs e)
{
(new EmailAddressChooserTask()).Show();
}
private void EmailMessageMenuItem_Click(object sender, EventArgs e)
{
(new EmailComposeTask()).Show();
}
private void MarketPlaceMenuItem_Click(object sender, EventArgs e)
{
MarketplaceLauncher.Show(MarketplaceContent.Applications, MarketplaceOperation.Open);
}
private void MediaPlayerMenuItem_Click(object sender, EventArgs e)
{
(new MediaPlayerLauncher()).Show();
}
private void PhoneCallMenuItem_Click(object sender, EventArgs e)
{
(new PhoneCallTask()).Show();
}
private void PhoneNumberMenuItem_Click(object sender, EventArgs e)
{
(new PhoneNumberChooserTask()).Show();
}
private void ChoosePhotoMenuItem_Click(object sender, EventArgs e)
{
(new PhotoChooserTask()).Show();
}
private void SaveEmailMenuItem_Click(object sender, EventArgs e)
{
(new SaveEmailAddressTask()).Show();
}
private void SavePhoneNumberMenuItem_Click(object sender, EventArgs e)
{
(new SavePhoneNumberTask()).Show();
}
private void SearchMenuItem_Click(object sender, EventArgs e)
{
(new SearchTask()).Show();
}
private void ComposeSMSMenuItem_Click(object sender, EventArgs e)
{
(new SmsComposeTask()).Show();
}
private void WebMenuItem_Click(object sender, EventArgs e)
{
(new WebBrowserTask()).Show();
}
}
}
Теперь, запустив приложение и выбрав какую-то из задач, можно убедиться, что они запускаются. Например, запустим задачу выбора изображений.

Теперь осталось задать обработчик результата. Воспользуемся для этого объектом ChooserListener
, и будем обрабатывать получение изображения от камеры. После выполнения задачи просто отобразим изображение на форме.
public MainPage()
{
InitializeComponent();
SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;
ChooserListener.ChooserCompleted += new EventHandler(ChooserListener_ChooserCompleted);
}
void ChooserListener_ChooserCompleted(object sender, EventArgs e)
{
if (e is TaskEventArgs<PhotoResult>)
{
var taskEventArgs = (TaskEventArgs<PhotoResult>)e;
var photoStream = taskEventArgs.Result.ChosenPhoto;
var bitmapImage = new BitmapImage();
bitmapImage.SetSource(photoStream);
image1.Source = bitmapImage;
}
}
Событие ChooserCompleted вызывается после завершения каждой задачи. Однако, в каждом случае тип аргумента будет разным. Например, для задачи CameraCaptureTask
аргумент будет иметь тип TaskEventArgs<PhotoResult>
. Поскольку камера отсутствует в эмуляторе, то вместо реального изображения там будут сгенерирована случайная картинка.

Таким образом, мы с вами имеем готовый API для того, чтобы выполнить ряд стандартных для мобильного устройства задач.
Добавить комментарий