Windows Phone 7

Seu primeiro aplicativo para Windows Phone

Jesse Liberty

Ao escrever o seu primeiro aplicativo para Windows Phone, o ideal é criar algo suficientemente interessante para que seja relevante, no entanto, simples o bastante para entrar realmente em atividade. Até o final desse documento, abordarei a criação de um utilitário simples que uso todos os dias: NoteToMe. A ideia é que você possa inserir uma mensagem e enviá-la a você mesmo pressionando um botão, conforme exibido na Figura 1.

The NoteToMe Interface
Figura 1 A interface NoteToMe

Observe que esse artigo abordará inúmeros tópicos e cada qual será amplamente descrito em artigos subsequentes. Esses tópicos incluem:

  • Criação do layout do aplicativo
  • Armazenamento e recuperação de dados no armazenamento isolado
  • Eventos e manipulação de eventos
  • Criação e execução de tarefas (iniciadores e seletores)

Antes de começar, é necessário fazer o download das ferramentas em xbox.http://xbox.create.msdn.com. Se você já desbloqueou o seu telefone, porém ainda não atualizou o Windows Phone 7.5 (“Mango”), agora é o momento de fazê-lo; o Mango acrescenta centenas de recursos novos ao SO do Windows Phone.

Introdução

Como muitos outros desenvolvedores do Windows Phone, eu acredito que a melhor ferramenta para criar aplicativos para o Windows Phone é uma combinação do Visual Studio (para o código) e do Expression Blend (para todo o restante). Portanto, vamos começar abrindo o Expression Blend e criando um novo aplicativo chamado NoteToMe, com base no SDK do Windows Phone 7.1.

Vamos iniciar alterando o título do aplicativo. Clique no título e localize a propriedade Texto na janela Propriedades para esse controle. As instruções de desenho Metro (para o Windows Phone) exigem que o título esteja em letras maiúsculas, portanto, altere o título para NOTE TO ME.

Clique no título da página e pressione Excluir para removê-lo.

Para criar o layout, você precisará de uma pequena linha próxima ao topo da página. Clique na margem para buscar uma instrução que o ajudará a selecionar visualmente o local para posicionar a linha, conforme exibido na Figura 2.

Placing the Top Row of the Layout
Figura 2 Posicionando a linha superior do layout

Obviamente, você pode configurar o tamanho da linha manualmente, diretamente no XAML:

<Grid.RowDefinitions>
  <RowDefinition Height="1*"/>
  <RowDefinition Height="9*"/>
</Grid.RowDefinitions>

O asterisco após o valor indica a proporção do tamanho, nesse caso, 1:9. Isto é, a primeira linha corresponderá a um nono do tamanho da segunda linha. 

Adicionando três controles ao StackPanel

A linha superior possuirá três controles, dispostos lado a lado:

  • Um TextBlock que atua como rótulo
  • Um TextBlock para armazenar o endereço de email
  • Um botão para enviar a mensagem

Esse desenho é mostrado na Figura 3.

Three Controls in the Top Row
Figura 3 Três controles na linha superior

Você não pode inserir três controles numa única coluna da linha sem inseri-los em algum tipo de contêiner organizador. Vamos usar um StackPanel cuja orientação foi configurada como horizontal; StackPanels são empilhados uns sobre os outros ou um do lado do outro.

Para criar um StackPanel, clique na seta branca pequena ao lado do controle de Layout, na barra de ferramentas, conforme mostrado na Figura 4.

Adding a StackPanel
Figura 4 Adicionando um StackPanel

Clique no StackPanel para selecionar o controle. Você pode agora arrastar um StackPanel para a linha e configurar o seu alinhamento vertical e horizontal para estendê-lo e definir as suas margens como zero na janela Layout, conforme mostrado na Figura 5.

Placing the StackPanel
Figura 5 Posicionando o StackPanel

Adicione o TextBlock, configurando a fonte para 32 e o texto como Para. Agora, arraste um TextBox para o StackPanel. (Observe a diferença importante e sutil entre um TextBlock para exibir o texto e um TextBox para a entrada de texto.) Nomeie esse TextBox como Endereço. Por último, adicione um botão ao StackPanel, chame-o de Enviar e configure o seu conteúdo como Enviar.

O XAML produzido por esse é mostrado na Figura 6.

Figura 6 Designando o StackPanel com XAML

<StackPanel
  Margin="0"
  Orientation="Horizontal">
  <TextBlock
    Margin="0,8"
    TextWrapping="Wrap"
    Text="To"
    Width="42"
    HorizontalAlignment="Left"
    VerticalAlignment="Center"
    FontSize="32" />
  <TextBox
    x:Name="Address"
    Margin="0,0,0,-7"
    TextWrapping="Wrap"
    Text="foo@bar.com"
    Width="293" />
  <Button
    x:Name="Send"
    Content="Send"
    Margin="0,4,0,0"
    Width="124"
    Click="Send_Click" />
</StackPanel>

Observe que o botão Enviar possui uma propriedade Click=“Send_Click”. Você cria essa propriedade clicando no botão e, em seguida, na janela Propriedades, clique no botão Eventos, conforme exibido na Figura 7.

The Events Button
Figura 7 Botão Eventos

Esse procedimento abre todos os eventos do botão. Localize o evento do clique e clique duas vezes sobre ele. O botão é atualizado com o evento e você será posicionado no editor do código (tanto no Blend quanto no Visual Studio, dependendo de como você configurou o Blend) para esse manipulador de eventos. Por agora, você pode deixar esse manipulador de eventos conforme ele está:

private void Send_Click( object sender, RoutedEventArgs e )
{
}

Adicionando o controle de mensagens

Clique no controle do TextBox na barra de ferramentas e, posteriormente, arraste um TextBox para preencher metade do restante da página (nós deixaremos a outra metade para o teclado, que será exibido na ocasião de inserir algo no TextBox). Configure o HorizontalAlignment para Estender, o VerticalAlignment para Superior e as margens para zero. Configure a largura para automático e a altura para 244. Você pode fazer tudo isso de olho à medida que dimensiona o TextBox, ou pode fazer um esboço do TextBox e configurar as propriedades na janela Propriedades, conforme ilustrado na Figura 8.

Adding the TextBox
Figura 8 Adicionando o TextBox

Escrevendo o código

Com os controles em posição, você poderá trabalhar com a lógica do programa. Você verá uma guia denominada Projetos no canto superior esquerdo. Depois de salvar todas as alterações, clique na guia Projetos e, posteriormente, clique com o botão direito em MainPage.xaml.cs e selecione Editar no Visual Studio, conforme mostrado na Figura 9.

Getting Ready to Write the Code
Figura 9 Preparando-se para escrever o código

Especificação

A minha especificação, cuja determinação é minha mesmo, afirma que você não deve ter que preencher o campo Para cada vez que usar o programa; esse campo deve ser preenchido previamente com o que já havia nele desde a utilização anterior.

Além do mais, quando você clicar em Enviar, um novo email deverá ser preparado para o seu programa de email, com todos os campos preenchidos, de modo que você apenas pressione Enviar ou possa editar a mensagem e, em seguida, pressionar Enviar.

Usando o Armazenamento isolado

Para preservar o conteúdo do campo Para em todas as utilizações do aplicativo, você precisará armazenar esse conteúdo em algum lugar no telefone. O armazenamento isolado se destina a: manter os dados quando o aplicativo foi fechado. Como o próprio nome indica, o armazenamento isolado permite que o aplicativo isole e proteja esses dados dos dados armazenados por outros aplicativos. Usar o Armazenamento isolado é muito simples.

Em primeiro lugar, adicione a instrução using:

using System.IO.IsolatedStorage;

Declare uma variável de membro do tipo IsolatedStorageSettings e uma cadeia de caracteres constante para atuar como chave para o dicionário do armazenamento isolado, de forma que você possa armazenar e recuperar o endereço de email:

private IsolatedStorageSettings _isoSettings;
const string IsoKey = "EmailAddress";
Initialize the _isoSettings member in the constructor:
 _isoSettings = IsolatedStorageSettings.ApplicationSettings;

Armazenando e recuperando o endereço de email

As duas tarefas relacionadas ao armazenamento isolado armazenarão a cadeia de caracteres e a recuperarão. É melhor realizar o armazenamento ao sair da página. Quando você sai de uma página do Windows Phone, o método OnNavigatedFrom é chamado. Você pode substituí-lo e um bom motivo para fazê-lo é armazenar os dados no armazenamento isolado, como a seguir:

protected override void OnNavigatedFrom(
  System.Windows.Navigation.NavigationEventArgs e )
{
  _isoSettings[IsoKey] = Address.Text;
  base.OnNavigatedFrom( e );
}

Agora, você possui o endereço de email armazenado no dicionário _isoSettings sob a chave IsoKey. Ao retornar à página, você poderá restaurar essa configuração. Eu faço isso chamando o método auxiliar privado RestoreEmailAddress a partir do construtor:

private void RestoreEmailAddress()
  {
    if (_isoSettings.Contains( IsoKey ))
      Address.Text = _isoSettings[IsoKey].ToString();
  }

Observe que devemos testar a existência da chave no armazenamento isolado antes de tentar restaurá-la, isso evita o acionamento da exceção KeyNotFound na primeira vez que o programa for executado. Lembre-se que na primeira vez que você executar o programa, você ainda não terá armazenado dados no armazenamento isolado.

Quando o programa for iniciado pela primeira vez, não haverá nada no campo Endereço. Quando o usuário insere um endereço de email no campo Endereço, este é guardado no armazenamento isolado e restaurado na próxima vez que o programa for executado. Se o usuário alterar o endereço, esse novo endereço será restaurado.

Tarefas

O Windows Phone 7.5 oferece suporte a diversas tarefas para a interação com os aplicativos integrados ao telefone (correio, lista de contados, câmera, etc.). Existem dois tipos de tarefas: Iniciadores e seletores. Os seletores são usados para selecionar informações e retorná-las ao programa (para obter um endereço de email a partir da lista de contato, por exemplo). Os iniciadores são usados para iniciar um programa que não retorna dados.

Nesse caso, você tem tudo o que precisa para enviar uma mensagem, portanto é possível chamar o Iniciador de email e preencher os campos necessários. Quando você chamar a opção Mostrar no Iniciador, os aplicativos de email serão iniciados com os seus dados, mas você não obterá os dados novamente (o que não causará problemas, pois você não precisará deles).

Depois de enviar o email, você será levado novamente ao programa, caso queira enviar outra mensagem.

Todo o trabalho de criação do Iniciador é encapsulado no manipulador de eventos de clique do botão Enviar. Vamos começar criando uma instância de EmailComposeTask (Iniciador). Preencha os campos e chame a opção Mostrar. Isso é tudo:

private void Send_Click( object sender, RoutedEventArgs e )
{
  EmailComposeTask emailComposeTask = new EmailComposeTask();
  emailComposeTask.Subject = "Send To Me";
  emailComposeTask.To = Address.Text;
  emailComposeTask.Body = Message.Text;
  Message.Text = String.Empty;
  emailComposeTask.Show();
}

Quando você chamar a opção Mostrar, o assunto, o endereço e o corpo da mensagem serão passados para o seu aplicativo de email. Se você possuir mais de um aplicativo de email, o sistema perguntará qual aplicativo deverá usar. Será criada uma mensagem de email com formatação e endereço adequados, pronta para ser enviada.

Ciclo de vida do aplicativo

Se fosse possível confiar que os usuários nunca interromperiam o uso do seu aplicativo até enviar a mensagem, isso seria tudo. Porém, na realidade, os usuários interrompem a composição de uma mensagem bem no meio e iniciam um aplicativo diferente. Ao retornarem, eles não ficarão contentes se o trabalho que tiveram for perdido.

Para saber como se proteger contra isso, você precisa entender um pouco sobre o ciclo de vida de um aplicativo e sobre o modo de preservar o estado enquanto oferece suporte a um dos recursos mais potentes do Mango: Troca rápida de aplicativo.

Quando o aplicativo for iniciado (do menu Iniciar, por exemplo), o evento de inicialização do aplicativo será acionado. Uma vez iniciado o aplicativo e sempre que o usuário navegar para a sua página, o método OnNavigatedTo será chamado e, feito isso, a sua página estará no estado de Execução. Se o usuário iniciar um novo aplicativo, este receberá um evento de Aplicativo Desativado e entrará no estado inativo. Se o telefone apresentar pouca memória, o aplicativo poderá ser marcado para exclusão.

Tanto do estado marcado para exclusão quanto do inativo, o aplicativo poderá ser encerrado ou restaurado. O que nos preocupa agora é o que ocorrerá quando o aplicativo for restaurado.

Se o aplicativo ficar inativo, você não deverá executar nenhuma ação quando este for restaurado, pois o seu estado foi preservado quando o aplicativo estava inativo e ele estará pronto para ser usado.

No entanto, se o aplicativo foi marcado para exclusão, você precisará restaurar a página quando o aplicativo retornar, de modo que este pareça estar sendo executado (ou, pelo menos, inativo) para o usuário, enquanto permanecia desativado.

Portanto, você precisa realizar duas tarefas:

  1. Salvar o estado quando o método OnNavigatedFrom da página for chamado.
  2. Restaurar potencialmente o estado quando o método OnNavigatedTo da página for chamado, restaurando assim o estado, se o aplicativo tiver sido marcado para exclusão, mas não se este estiver inativo.

Salvando o estado quando a página desaparecer

Já que você não conhece o estado da página quando esta for restaurada ao receber o OnNavigatedFrom, você deve armazenar o estado, caso este seja necessário. Isso é muito fácil de fazer: você usa o dicionário Estado, que é muito semelhante ao dicionário do armazenamento isolado com relação à sintaxe, embora seja necessário lembrar que o dicionário Estado não foi escrito para armazenamento permanente e, de fato, este será destruído quando você sair do programa ou desligar o telefone.

Vamos começar criando um cadeia de caracteres constante StateKey, que você deverá usar como referência no dicionário Estado:

const string StateKey = "MessageState";

No método OnNavigatedFrom, você armazenará o estado (nesse caso, o conteúdo de MessageBox) no dicionário Estado:

protected override void OnNavigatedFrom(
  System.Windows.Navigation.NavigationEventArgs e )
{
  _isoSettings[IsoKey] = Address.Text;
  State[StateKey] = Message.Text;
  base.OnNavigatedFrom( e );
}

Restaurando o estado quando a página for criada

Quando o método OnNavigatedTo for chamado, você não precisará executar nenhuma ação para restaurar o Estado, se o aplicativo estiver inativo, mas você precisará executar uma ação se ele estiver marcado para exclusão.

Você pode distinguir entre o estado inativo ou marcado para exclusão configurando um sinalizador como falso e, em seguida, configurando-o como verdadeiro no construtor. Se o aplicativo estiver inativo, o construtor não será chamado; se ele tiver sido marcado para exclusão, o construtor será chamado (porque será a primeira vez que ele é construído), como a seguir:

bool isNew = false;
  public MainPage()
  {
    InitializeComponent();
    isNew = true;

Você pode verificar esse sinalizador no OnNavigatedTo:

protected override void OnNavigatedTo(
  System.Windows.Navigation.NavigationEventArgs e )
{
  if (isNew)
  {
    if (State.ContainsKey( StateKey ))
    {
      Message.Text = State[StateKey].ToString();
    }
  }
  isNew = false;
  base.OnNavigatedTo( e );
}

Este teste poupa o tempo que seria gasto, o que não ocorreria na restauração do valor do dicionário Estado. Você pode testar isso executando primeiro o programa de forma normal (nesse caso, quando você mudar para outro aplicativo, o seu programa ficará inativo) e, em seguida, forçando o programa a ser marcado para exclusão. É possível forçar o programa a ser marcado para exclusão clicando com o botão direito no projeto, selecionando Propriedades, selecionando a guia Depurar e marcando a caixa de seleção Marcar para exclusão na desativação, durante a depuração.

Ao executar o programa com essa caixa de seleção marcada, você perceberá claramente uma pausa ao retornar para a página porque o estado deve ser restaurado.

Visão geral final

Neste breve artigo, vimos como escrever o seu primeiro aplicativo não trivial para Windows Phone. Começamos criando o aplicativo no Expression Blend, onde eu criei uma linha e utilizei um StackPanel para acomodar os controles.

Posteriormente, eu mudei para o Visual Studio para escrever a lógica para o manipulador de eventos do botão e usei o armazenamento isolado para manter o endereço de email. Usamos a memória do Estado para garantir que o aplicativo inicie adequadamente depois de ser marcado para exclusão.

Como observado, há muito mais a ser dito em cada um desses tópicos e eles serão abordados em detalhes em artigos futuros.

Jesse Liberty é um divulgador sênior da comunidade de desenvolvedores da equipe do Windows Phone. Liberty hospeda o popular "Yet Another Podcast" (jesseliberty.com/podcast), e o seu blog (jesseliberty.com/) é uma leitura obrigatória. Ele é o autor de numerosos best-sellers, inclusive de “Programming Reactive Extensions and LINQ” (Apress, 2011) e “Migrating to Windows Phone,” (Apress, 2011). Você pode segui-lo no Twitter, em twitter.com/JesseLiberty.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Drew Batchelor e Cheryl Simmons