A Universal Windows Platform (UWP) é uma plataforma unificada para o desenvolvimento de aplicações que rodem em dispositivos que executam o Windows 10, como tablets, smartphones, computadores e o Xbox. Claro que por terem diferentes capacidades e componentes, em alguns casos é necessário desenvolver um código específico para cada dispositivo, mas a API de desenvolvimento do UWP facilita muito esse trabalho, evitando ter que reescrever a aplicação para cada plataforma.

Quando desenvolvemos aplicações para o Windows 8 escolhemos em qual plataforma a mesma seria executada (desktop ou no Windows Phone). Na versão atual escolhemos para quais famílias de dispositivos a aplicação será executada, como computadores (notebook e desktop), dispositivos móveis (smartphones e tablets), Xbox, entre outras. Todas elas possuem a API da UWP e um subconjunto de APIs específicas para cada tipo de dispositivo.

Caso a aplicação não utilize nenhuma API específica, ela pode ser utilizada em qualquer dispositivo que execute o Windows 10, como é o caso da que desenvolveremos nesse artigo.

A aplicação terá três interfaces: a primeira para listar a atividade, uma para o cadastro de pessoas e uma para a listagem das pessoas cadastradas. Todo o código será desenvolvido com o Visual Studio Community 2015, que é livre para fins de estudos. Caso queira desenvolver aplicações comerciais com essa ferramenta, na seção Links encontram-se as informações sobre licenças do Visual Studio.

Desenvolvimento da Aplicação

Em uma aplicação UWP utilizamos as linguagens C# e XAML (Extensible Application Markup Language) para o desenvolvimento das interfaces de usuários. Esta última é uma linguagem de marcação simples que contém formulários, listas e tabelas, ideais para a criação de UI. Todo XAML tem uma classe C# associada chamada de Code behind, que controla os eventos que acontecem na visão. A Listagem 1 mostra o código básico de um XAML.


<Page
x:Class="App5.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="using:App5"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            mc:Ignorable="d">
 
            <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">     
 
            </Grid>
</Page>
Listagem 1. XAML básico
Nota: A UWP não está presente na instalação padrão do Visual Studio, por isso, na criação do primeiro projeto os arquivos necessários serão baixados, porém, não é necessária nenhuma ação do usuário, pois basta esperar que a IDE baixe os arquivos e faça as configurações necessárias.

Para iniciar o desenvolvimento criamos um projeto do tipo Universal Windows no Visual Studio, como mostra a Figura 1.

Criação do projeto no Visual Studio
Figura 1. Criação do projeto no Visual Studio

Com isso já é criado o primeiro arquivo XAML, que terá as interfaces com o usuário. A página inicial MainPage terá apenas três botões de navegação para as interfaces de cadastro, listagem e busca. Em seguida, devemos criar uma classe simples chamada Pessoa, que tem apenas os atributos Nome e Telefone e seus métodos get e set, como mostra o código da Listagem 2.


namespace App5
{
    public class Pessoa
    {
        public string Nome { set; get; }
        public string Telefone { set; get; }
    }
}
Listagem 2. Classe Pessoa que será usada em toda a aplicação

Para organizar a disposição dos elementos dentro da tela utilizaremos o código da Listagem 3, que exibe o código do XAML da tela principal. Este utiliza o componente <StackPanel>. Com isso eles ficam organizados em um painel como uma pilha, um abaixo do outro. Dentro do painel existem dois botões declarados com o componente . A configuração para cada um deve ser:

  • O atributo Content define o texto que será exibido dentro do botão;
  • O atributo Margin define o espaçamento entre os botões;
  • O evento Click define o método que será chamado na classe code-behind quando um usuário clicar no botão.

<Page
  x:Class="App5.MainPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="using:App5"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="d">

     <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
     <StackPanel Name="Panel" VerticalAlignment="Center" HorizontalAlignment="Center">
           <TextBlock Name="Titulo" Text="Lista de Telefone" FontSize="30" 
           HorizontalAlignment="Center" />
           <Button Name="btCadastrar" Click="cadastrar_action" Margin="20" Content="Cadastrar" 
           Width="100" HorizontalAlignment="Center"/>
           <Button Name="btListar" Click="listar_action" Margin="20" Content="Listar" Width="100" 
           HorizontalAlignment="Center"/>
     </StackPanel>
     </Grid>
</Page>
Listagem 3. XAML da tela principal

Outra característica interessante do Visual Studio é o desenvolvimento dos XAML sem a necessidade de programação, apenas utilizando drag and drop de componentes e editando algumas características visuais na própria visualização da tela. Ele permite também a alteração de diversas propriedades dos componentes na aba Properties. A Figura 2 mostra uma imagem da visualização da interface.

Programação visual no Visual Studio 2015
Figura 2. Programação visual no Visual Studio 2015

Para cada botão que faz a navegação da página principal para as outras páginas da aplicação temos a codificação da Listagem 4, que mostra o código da classe code-behind do XAML MainPage, com um método para cada botão.

O trecho de código this.Frame.Navigate(typeof(Cadastro)) define a navegação da página atual para a página cadastro (que ainda vamos criar) e os outros métodos fazem a mesma coisa para as outras telas da aplicação.


namespace App5
{
  /// <summary>
  /// An empty page that can be used on its own or navigated to within a Frame.
  /// </summary>
  public sealed partial class MainPage : Page
  {
      public MainPage()
      {
           this.InitializeComponent();
      }

      // faz a navegação para tela Cadastrar
      public void cadastrar_action(object sender, RoutedEventArgs e)
      {
           this.Frame.Navigate(typeof(Cadastrar));

      }

      // faz a navegação para tela listar
      public void listar_action(object sender, RoutedEventArgs e)
      {
           this.Frame.Navigate(typeof(Listar));

      }

  }
}
Listagem 4. Code-Behind da página MainPage

A Listagem 5 mostra o código da tela de cadastro que tem dois campos de texto declarados com a tag : um campo para o cadastro do nome da pessoa e o outro para o cadastro do telefone. Além disso existe um Label declarado com a tag com o título da página “Cadastro de Contato”. Temos também um botão de onde a ação de cadastrar a pessoa será executada.


<Page
    x:Class="App5.Cadastrar"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App5"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
 
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel Name="Panel" VerticalAlignment="Center" HorizontalAlignment="Center">
             <TextBlock Name="Titulo" Text="Cadastro de Pessoa" HorizontalAlignment="Center" />
             <TextBox PlaceholderText="Nome" Name="Nome" Width="138" Margin="20" ></TextBox>
             <TextBox PlaceholderText="Telefone"  Name="Telefone" Width="138" Margin="20" >
             </TextBox>
             <Button Name="btCadastrar" Margin="20" Content="Cadastrar" HorizontalAlignment="Center" 
             Click="Button_Click" Width="100"/>
        </StackPanel>
    </Grid>
</Page>
Listagem 5. XAML da tela de cadastro

Nessa tela também é utilizado um que é colocado no centro da tela com os atributos VerticalAlignment e HorizontalAlignment. No componente são utilizados os seguintes atributos:

  • PlaceholderText, que exibe um texto inicial para o componente que é apagado assim que o usuário clica nele;
  • Width, que define o tamanho do campo na tela;
  • Margin, para definir o espaçamento entre os campos do formulário;
  • E o atributo Name para definir o nome do componente, já que esses campos serão chamados na classe code-behind dessa tela.

A Listagem 6 mostra esse code-behind da tela de cadastro. Nele existe o método Button1_click, que será executado a partir da ação de click do botão da tela de cadastro. No código deste é feita a adição dos dados da pessoa em uma lista de pessoas que está declarada na própria classe. Como esta lista é estática, ela pode ser acessada de qualquer parte da aplicação.

Para essa aplicação não vamos utilizar um banco de dados, mas fique à vontade para adaptar a mesma com o SQLite, por exemplo.

Depois do cadastro da pessoa é feita a navegação de volta para a tela inicial da aplicação.


namespace App5
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class Cadastrar : Page
    {
        public Cadastrar()
        {
             this.InitializeComponent();
        }
 
        //ação do botão cadastrar. Cadastra a pessoa e volta para a tela inicial
        private void Button_Click(object sender, RoutedEventArgs e)
        {
             Pessoa pessoa = new Pessoa();
             pessoa.Nome = Nome.Text;
             pessoa.Telefone = Telefone.Text;
 
             App.pessoas.Add(pessoa);
 
             this.Frame.Navigate(typeof(MainPage));
        }
    }
}
Listagem 6. Code-Behind da tela de cadastro

A outra tela da aplicação lista todas as pessoas cadastradas usando o Data Binding, que é um conceito presente na maioria das plataformas hoje em dia. Este permite a vinculação de elementos de código com elementos da visão do usuário, diminuindo a necessidade de código escrito.

A Listagem 7 mostra o código fonte do XAML da tela de listagem de pessoas, que usa o padrão ViewModel. Este inclui uma classe que é responsável por recuperar os dados e enviá-los para a página através da tag . Além disso, é necessário adicionar o atributo xmlns:vm="using:App5" na tag , onde o valor using:App5 é o namespace da classe ViewModel.

Depois é declarado o componente ListView, que exibe uma lista de Items. O Data Binding é feito no atributo ItemsSource, vinculado a um objeto chamado Items, que será declarado na classe do ViewModel desta tela.

Existe também uma vinculação no atributo Header, onde será passado o título da listagem, assim essa tela pode ser genérica e usada em qualquer listagem de pessoas. Os componentes são vinculados aos atributos Nome e Telefone declarados na classe Pessoa.


<Page
    x:Class="App5.Listar"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App5"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="using:App5"
    mc:Ignorable="d">
 
    <Page.DataContext>
        <vm:PessoaViewModel />
    </Page.DataContext>
 
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ColumnDefinitions>
             <ColumnDefinition/>
             <ColumnDefinition/>
        </Grid.ColumnDefinitions>
 
        <ListView Name="lvPessoas" ItemsSource="{Binding Items}" Header="{Binding ListName}" 
        Grid.Column="0">
             <ListView.ItemTemplate>
             <DataTemplate>
                    <StackPanel>
                     <TextBlock Name="tbNome" Text="{Binding Nome}" FontSize="20"/>
                        <TextBlock Name="tbTelefone" Text="{Binding Telefone}" FontSize="16"  />
                    </StackPanel>
             </DataTemplate>
             </ListView.ItemTemplate>
        </ListView>
 
        <StackPanel Name="Panel" VerticalAlignment="Center" HorizontalAlignment="Right" 
        Grid.Column="1">
             <Button Name="btVoltar" Margin="20" Content="Voltar" Width="100" Click="Button_Click"/>
        </StackPanel>
    </Grid>
</Page>
Listagem 7. XAML para a listagem de pessoas

Para recuperar os dados e exibi-los na tela de listagem é necessário criar a classe ViewModel, presente no código da Listagem 8.

No próprio construtor da classe é recuperado os dados da lista de pessoas que são adicionados na lista Items. Esta é vinculada ao Data Binding pelo ListView da tela mostrada anteriormente.

A classe ObservableCollection funciona como um List, mas é utilizada quando é feito DataBinding. Como vantagem, caso ela seja modificada, a classe notifica automaticamente a View, que é atualizada com as modificações. Para utilizá-la é necessário declarar o namespace System.Collections.ObjectModel.

Além disso, existe a string ListName, que mostra o título a ser exibido no ListView da tela de listagem das pessoas.


using System.Collections.ObjectModel;
namespace App5
{
    class PessoaViewModel
    {
 
        //Coloca as pessoas na lista vinculada a visão
        public PessoaViewModel()
        {
             ListName = "Lista de Pessoas";
             for (int i = 0; i < App.pessoas.Count; i++)
             {
             Pessoa pessoa = App.pessoas.ElementAt(i);
             this.Items.Add(pessoa);
             }
 
        }
       
        //lista de pessoas que serão exibidas na tela
        public ObservableCollection<Pessoa> Items
        {
             get; set;
        } = new ObservableCollection<Pessoa>();
 
        public string ListName { get; set; }
    }
}
Listagem 8. ViewModel da tela de listagem

A classe code-behind da tela de listagem, presente na Listagem 9, tem apenas a ação que é disparada quando o usuário aperta o botão Voltar. Esse método volta para a tela MainPage.


namespace App5
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class Listar : Page
    {
        public Listar()
        {
             this.InitializeComponent();
        }
 
        //faz a navegação de volta para a tela principal
        private void Button_Click(object sender, RoutedEventArgs e)
        {
             this.Frame.Navigate(typeof(MainPage));
        }
 
    }
}
Listagem 9. Code-behind da tela de listagem

A lista de pessoas que são salvas na tela Cadastrar e que são exibidas na tela de listagem foi declarada na classe App que todo projeto da UWP tem. Essa classe é utilizada para fazer algumas configurações iniciais da aplicação e também para controlar o ciclo de vida da mesma, por meio de alguns métodos:

  • OnLaunched, para definir o comportamento da aplicação assim que ela é iniciada;
  • OnNavigationFailed, que define o comportamento quando a navegação falha;
  • OnSuspending, que define o que fazer quando a execução da aplicação é suspensa.

A Listagem 10 mostra o código que deve ser adicionado nessa classe. Este pode ser adicionado em qualquer posição que esteja fora de um método dentro da classe, mas recomendamos que seja logo no início da classe.


sealed partial class App : Application
{
       public static List<Pessoa> pessoas = new List<Pessoa>();
            //outro código aqui gerado automaticamente pelo Visual Studio
}
Listagem 10. Lista de pessoas declarada na classe App

A Figura 3 mostra a aplicação sendo executada como uma aplicação normal do Windows: a direita está a tela principal com os botões para a navegação entre as telas; no centro a tela para cadastro de pessoas com os componentes de formulário e o botão cadastrar; e por último, a esquerda, a tela de listagem de pessoas cadastradas.

Três telas da aplicação na máquina local
Figura 3. Três telas da aplicação na máquina local

Essa aplicação pode ser executada também no emulador do Windows Phone. A Figura 4 mostra as opções para a execução da aplicação no Visual Studio. Repare que é possível rodar a app na máquina local, em uma máquina remota, em um simulador e nos emuladores do Windows Phone.

Opções de execução de uma aplicação UWP
Figura 4. Opções de execução de uma aplicação UWP

Caso tenha um dispositivo Windows Phone disponível, é possível executar a aplicação diretamente no mesmo.

Com isso vimos que a API UWP é uma ferramenta muito poderosa para o desenvolvimento de aplicações voltadas a família de dispositivos Microsoft. Além de ser muito fácil desenvolver uma aplicação nesta plataforma, também é possível executar a mesma versão da aplicação, com nenhuma ou muito pouca alteração no código, em vários dispositivos diferentes, tudo isso unido a IDE Visual Studio.