×
Namespaces

Variants
Actions

Criando uma página "Sobre" para aplicações em Windows Phone

From Nokia Developer Wiki
Jump to: navigation, search

Este artigo tem como objetivo mostrar como criar uma página avançada “Sobre”, também conhecida por página “Acerca de”, e iremos também abordar pontos para podermos reutilizar a página.

Note.pngNote: Este artigo foi publicado na Revista Programar nº40 iniciando na página 62.

WP Metro Icon UI.png
SignpostIcon XAML 40.png
WP Metro Icon WP8.png
SignpostIcon WP7 70px.png
Article Metadata

Exemplo de código
Código fonte: About Page Sample (Github)

Testado com
SDK: Windows Phone SDK 7.1
Aparelho(s): Nokia Lumia

Compatibilidade
Artigo
Tradução:
Por saramgsilva
Última alteração feita por saramgsilva em 05 Nov 2013

Contents

Introdução

Cada aplicação que é desenvolvida para publicação na loja de aplicativos, deve conter uma página de informações sobre o aplicativo ("Sobre" ou “Acerca de”). Esta página tem como objetivo apresentar informações relevantes sobre a aplicação.

De uma forma geral existe um padrão para se contruir essa página. Por exemplo, estes são os pontos principais:

  • Nome da aplicação
  • Versão da aplicação
  • Direitos de autor
  • Resumo dos detalhes da aplicação
  • Referência web da aplicação, suporte e políticas de privacidade.

Outras funcionalidades que podem ser relevantes para esta página são:

  • Avaliar a aplicação
  • Enviar "Feedback" para o dono
  • Partilhar a aplicação via correio eletrónico
  • Partilhar a aplicação via redes sociais

Em alguns casos, algumas aplicações podem apresentar mais detalhes sobre a aplicação. Por exemplo, o histórico da aplicação, regras externas, entre outros detalhes.


Telas da aplicação

As duas primeiras figuras mostram a página principal - "HomePage" (com ApplicationBar aberta e fechada, respetivamente) de onde podemos lançar a página "AboutPage". As outras duas figuras mostram a página "AboutPage" (com ApplicationBar aberta e fechada, respetivamente).


HomePage.xaml - closed appbar HomePage.xaml - opened appbar


AboutPage.xaml  - closed appbar AboutPage.xaml - opened appbar

Note.pngNote: HomePage.xaml tem dois botões "About" porque existem dois sítios onde podemos encontrar esta opção, no sentido de ajudar, implementamos em ambos os sítios.

Código fonte

O código fonte pode ser encontrado no : About Page Sample (*)

(*) Exemplo disponível, apenas, em Inglês.

Pré - Requisitos

O exemplo usa o padrão de desenvolvimento Model-View-ViewModel (MVVM), que é o padrão recomendado para o desenvolvimento de aplicações para Windows Phone..


Os elementos do padão MVVM são:

  • Views - representa as páginas (está relacionado com a UI).
  • ViewModel - representa as classes que serão usadas para conectar a interface com o modelo de dados.
  • Model - representa as classes que definem as entidades e a lógica de negócio.


Diagrama com um sumário sobre o padrão MVVM.


Para ajudar na implementação do padrão MVVM existem vários toolkits. Para este exemplo, iremos usar os seguintes toolkits:

Os pacotes são disponíveis através do Nuget Package Manager (para ambos os targets) e podem ser instalados da seguinte forma:

  1. Abrir o projeto e selecionar References, em seguinda abrir o menu de contexto usando o rato (botão direito) e selecionar "Manage NuGet Packages ..."
    Seleção do "Manage NuGet Packages ..."
  2. Instalação do MVVM Light toolkit (para mais informações sobre este pacote consultar esta referência)
    Procurar por MVVM Light
    MVVM Light toolkit está instalado.
  3. Instalação do Cimbalino toolkit (para mais informações sobre este pacote consultar esta referência)
    Procurar por Cimbalino
    Cimbalino toolkit está instalado.
  4. Os seguintes passos mostram como podemos ver os pacotes instalados.
    Installedtoolkits.png

Nota: (*) Artigos disponível, apenas, em Inglês.

Criação da página Sobre

Este exemplo é válido para as várias versões do Windows Phone SDK, não sendo relevante se estamos a desenvolver para Windows Phone OS 7.1 ou para Windows Phone OS 8.0, desta forma podemos selecionar o que quisermos. No Código Fonte, podemos encontrar o exemplo completo para ambos os casos

Comecemos com a criação do projeto, o template Windows Phone App foi o selecionado no exemplo.

Em seguida, iremos criar:

  • ViewModels - pasta que contém todas as view models;
  • Views - pasta que contém todas as vistas;
  • HomePage - representa a página principal;
  • AboutPage - representa a página "Acerca de";
  • HomeViewModel - representa a view model que será aplicada à página principal;
  • AboutViewModel - representa a view model que será aplicada à página "Acerca de"; ViewModelLocator - representa a classe de ajuda para conectar as view models com as views;


O resultado será:

Estrutura do projeto.


Home Page.xaml

A página HomePage será a primeira página a ser apresentada quando a aplicação inicia. Esta página contém o controlo WebBrowser para mostrar este artigo e contém o botão About. O XAML define toda a interface com o utilizador para a HomePage. Note-se, como estamos a usar o padrão MVVM, toda a lógica estará definida na view model HomeViewModel que será usada no binding com o DataContext.

<phone:PhoneApplicationPage
x:Class="NokiaDev.AboutPageSample.Views.HomePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cimbalino="clr-namespace:Cimbalino.Phone.Toolkit.Behaviors;assembly=Cimbalino.Phone.Toolkit"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
DataContext="{Binding HomeViewModel, Source={StaticResource Locator}}"
mc:Ignorable="d"
shell:SystemTray.IsVisible="True">
 
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
 
<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="Nokia Developer Wiki Samples" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="Article" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
<TextBlock Text="About page for Windows Phone applications"
FontSize="{StaticResource PhoneFontSizeSmall}"
Foreground="{StaticResource PhoneAccentBrush}"
Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
 
</StackPanel>
 
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:WebBrowser Source="http://www.developer.nokia.com/Community/Wiki/Advanced_About_Page_for_Windows_Phone_apps" />
</Grid>
<i:Interaction.Behaviors>
<cimbalino:ApplicationBarBehavior>
<cimbalino:ApplicationBarIconButton Command="{Binding AboutCommand, Mode=OneTime}"
IconUri="/Images/appbar.about.png"
Text="About" />
<cimbalino:ApplicationBarBehavior.MenuItems>
<cimbalino:ApplicationBarMenuItem Command="{Binding AboutCommand, Mode=OneTime}"
Text="About"/>
</cimbalino:ApplicationBarBehavior.MenuItems>
</cimbalino:ApplicationBarBehavior>
</i:Interaction.Behaviors>
</Grid>
</phone:PhoneApplicationPage>

No final do código do XAML, é possível ver a definição para a ApplicationBar que usa o ApplicationBarBehavior do Cimbalino Toolkit. A razão pela qual não estamos aplicar o controlo ApplicationBar do SDK está relacionado ao fato de este controlo não ser um FrameworkElement e não é possível aplicar bindings, o que é um problema para quem pretende implementar o padrão MVVM.

Para mais informações sobre o ApplicationBarBehavior do Cimbalino Toolkit, consultar:

Nota: (*) Artigos disponível, apenas, em Inglês.

AboutPage.xaml

A página AboutPage será apresentada para mostrar a informação "Sobre" / "Acerca de" da aplicação. Esta página contém alguns controlos para mostrar os pontos descritos na Introdução e contém botões para as várias funcionalidades. A interface com o utilizador da página AboutPage é a seguinte. Note-se, como estamos a usar o padrão MVVM, toda a lógica estará definida na view model AboutViewModel que será usada no binding com o DataContext.


<phone:PhoneApplicationPage
x:Class="NokiaDev.AboutPageSample.Views.AboutPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cimbalino="clr-namespace:Cimbalino.Phone.Toolkit.Behaviors;assembly=Cimbalino.Phone.Toolkit"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
DataContext="{Binding AboutViewModel, Source={StaticResource Locator}}"
mc:Ignorable="d"
shell:SystemTray.IsVisible="True">
 
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
 
<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="Nokia Developer Wiki Samples" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="About" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
 
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Margin="0,-12,0,24">
<TextBlock Style="{StaticResource PhoneTextExtraLargeStyle}"
Text="About Page Sample"
Foreground="{StaticResource PhoneAccentBrush}" />
<TextBlock Style="{StaticResource PhoneTextLargeStyle}">
by <Run Text="{Binding Author}" />
</TextBlock>
 
 
<StackPanel Orientation="Horizontal" Margin="0,18,0,0">
<TextBlock FontWeight="Bold"
FontSize="{StaticResource PhoneFontSizeMedium}"
Style="{StaticResource PhoneTextNormalStyle}" Text="Version:" />
<TextBlock Margin="0" Text="{Binding Version}"
Style="{StaticResource PhoneTextNormalStyle}" x:Name="AppVersion" />
</StackPanel>
 
<TextBlock Style="{StaticResource PhoneTextNormalStyle}"
FontSize="{StaticResource PhoneFontSizeMedium}"
Margin="12,12,0,0" FontWeight="Bold"
Text="Copyright (c) 2013 Nokia Developer Wiki." />
 
<TextBlock Style="{StaticResource PhoneTextNormalStyle}"
Margin="12,24,0,0" FontSize="{StaticResource PhoneFontSizeSmall}"
TextWrapping="Wrap">
This application show an 'About page' sample for Windows Phone applications.
<LineBreak/>See more about it, please see the following reference:
</TextBlock>
<HyperlinkButton NavigateUri="http://www.developer.nokia.com/Community/Wiki/About_page_for_Windows_Phone_applications"
Foreground="{StaticResource PhoneAccentBrush}"
TargetName="_new" FontSize="{StaticResource PhoneFontSizeSmall}"
HorizontalAlignment="Left"
Content="About page for Windows Phone applications" />
 
<TextBlock Style="{StaticResource PhoneTextNormalStyle}"
Margin="12,24,0,12" FontWeight="Bold"
Text="More informations:"
FontSize="{StaticResource PhoneFontSizeMedium}" />
 
<HyperlinkButton NavigateUri="http://www.developer.nokia.com/"
Foreground="{StaticResource PhoneAccentBrush}"
TargetName="_new"
HorizontalAlignment="Left"
Content="Website" />
 
<HyperlinkButton NavigateUri="http://www.developer.nokia.com/"
Foreground="{StaticResource PhoneAccentBrush}"
TargetName="_new"
HorizontalAlignment="Left"
Content="Support" />
 
<HyperlinkButton NavigateUri="http://www.developer.nokia.com/"
Foreground="{StaticResource PhoneAccentBrush}"
TargetName="_new"
HorizontalAlignment="Left"
Content="Privacy Policy" />
 
</StackPanel>
</Grid>
 
<i:Interaction.Behaviors>
<cimbalino:ApplicationBarBehavior>
<cimbalino:ApplicationBarIconButton Command="{Binding RateCommand, Mode=OneTime}"
IconUri="/Images/appbar.rate.png"
Text="Rate it" />
<cimbalino:ApplicationBarIconButton Command="{Binding SendFeedbackCommand, Mode=OneTime}"
IconUri="/Images/appbar.reply.email.png"
Text="Feedback" />
<cimbalino:ApplicationBarIconButton Command="{Binding ShareToMailCommand, Mode=OneTime}"
IconUri="/Images/appbar.email.png"
Text="Email" />
<cimbalino:ApplicationBarIconButton Command="{Binding ShareSocialNetworkCommand, Mode=OneTime}"
IconUri="/Images/appbar.share.png"
Text="Share it" />
</cimbalino:ApplicationBarBehavior>
</i:Interaction.Behaviors>
</Grid>
</phone:PhoneApplicationPage>

Assim como foi mostrado na página HomePage, nesta página usamos ApplicationBarBehavior do Cimbalino Toolkit para definir a application bar com suporte a binding.

HomeViewModel.cs

A Home Page view model é a seguinte:

namespace NokiaDev.AboutPageSample.ViewModels
{
using System;
using System.Windows.Input;
 
using Cimbalino.Phone.Toolkit.Services;
 
using GalaSoft.MvvmLight.Command;
 
/// <summary>
/// The home view model.
/// </summary>
public class HomeViewModel
{
/// <summary>
/// The navigation service.
/// </summary>
private readonly INavigationService _navigationService;
 
/// <summary>
/// Initializes a new instance of the <see cref="HomeViewModel"/> class.
/// </summary>
/// <param name="navigationService">
/// The navigation service.
/// </param>
public HomeViewModel(INavigationService navigationService)
{
this._navigationService = navigationService;
this.AboutCommand = new RelayCommand(this.ShowAbout);
}
 
/// <summary>
/// Gets the about command.
/// </summary>
/// <value>
/// The about command.
/// </value>
public ICommand AboutCommand { get; private set; }
 
/// <summary>
/// The show about.
/// </summary>
private void ShowAbout()
{
this._navigationService.NavigateTo(new Uri("/Views/AboutPage.xaml", UriKind.Relative));
}
}
}


Na implementação usamos

A seguinte imagem mostra o fluxo:

HomePage Aboutbutton.png

AboutViewModel.cs

A About Page view model é a seguinte:

namespace NokiaDev.AboutPageSample.ViewModels
{
using System;
using System.Windows.Input;
 
using Cimbalino.Phone.Toolkit.Helpers;
using Cimbalino.Phone.Toolkit.Services;
 
using GalaSoft.MvvmLight.Command;
 
/// <summary>
/// The about view model.
/// </summary>
public class AboutViewModel
{
/// <summary>
/// The email compose service.
/// </summary>
private readonly IEmailComposeService _emailComposeService;
 
/// <summary>
/// The marketplace review service.
/// </summary>
private readonly IMarketplaceReviewService _marketplaceReviewService;
 
/// <summary>
/// The share link service.
/// </summary>
private readonly IShareLinkService _shareLinkService;
 
/// <summary>
/// The public application url.
/// </summary>
private readonly string _appUrl;
 
/// <summary>
/// The application manifest.
/// </summary>
private readonly ApplicationManifest _applicationManifest;
 
/// <summary>
/// Initializes a new instance of the <see cref="AboutViewModel"/> class.
/// </summary>
/// <param name="emailComposeService">
/// The email Compose Service.
/// </param>
/// <param name="applicationManifestService">
/// The application Manifest Service.
/// </param>
/// <param name="marketplaceReviewService">
/// The marketplace review service
/// </param>
/// <param name="shareLinkService">
/// The share Link Service.
/// </param>
public AboutViewModel(
IEmailComposeService emailComposeService,
IApplicationManifestService applicationManifestService,
IMarketplaceReviewService marketplaceReviewService,
IShareLinkService shareLinkService)
{
_emailComposeService = emailComposeService;
_marketplaceReviewService = marketplaceReviewService;
_shareLinkService = shareLinkService;
RateCommand = new RelayCommand(this.Rate);
SendFeedbackCommand = new RelayCommand(this.SendFeedback);
ShareToMailCommand = new RelayCommand(this.ShareToMail);
ShareSocialNetworkCommand = new RelayCommand(this.ShareSocialNetwork);
_applicationManifest = applicationManifestService.GetApplicationManifest();
_appUrl = string.Concat("http://windowsphone.com/s?appid=", _applicationManifest.App.ProductId);
}
 
/// <summary>
/// Gets the author.
/// </summary>
public string Author
{
get
{
return _applicationManifest.App.Author;
}
}
 
/// <summary>
/// Gets the version.
/// </summary>
public string Version
{
get
{
return _applicationManifest.App.Version;
}
}
 
/// <summary>
/// Gets the rate command.
/// </summary>
public ICommand RateCommand { get; private set; }
 
/// <summary>
/// Gets the send feedback command.
/// </summary>
public ICommand SendFeedbackCommand { get; private set; }
 
/// <summary>
/// Gets the share social network command.
/// </summary>
public ICommand ShareSocialNetworkCommand { get; private set; }
 
/// <summary>
/// Gets the share to e-mail command.
/// </summary>
public ICommand ShareToMailCommand { get; private set; }
 
/// <summary>
/// The rate.
/// </summary>
private void Rate()
{
_marketplaceReviewService.Show();
}
 
/// <summary>
/// The send feedback.
/// </summary>
private void SendFeedback()
{
const string To = "saramgsilva@gmail.com";
const string Subject = "My Feedback";
var body = string.Format(
"Application {0}\n Version: {1}",
_applicationManifest.App.Title,
_applicationManifest.App.Version);
_emailComposeService.Show(To, Subject, body);
}
 
/// <summary>
/// The share social network.
/// </summary>
private void ShareSocialNetwork()
{
const string Message = "This application is amazing, should try it! See in";
_shareLinkService.Show(_applicationManifest.App.Title, Message, new Uri(_appUrl, UriKind.Absolute));
}
 
/// <summary>
/// The share to mail.
/// </summary>
private void ShareToMail()
{
const string Subject = "Nokia Developer Wiki Samples - About page";
var body = string.Concat("This application is amazing, you should try it! See in", _appUrl);
_emailComposeService.Show(Subject, body);
}
}
}

Na implementação usamos

RelayCommand class, cujo código fonte é este, representa a implementação da interface ICommand .

IEmailComposeService interface, cujo código fonte é este, representa o serviço com a capacidade de enviar messagens via e-mail. A implementação é EmailComposeService

IMarketplaceReviewService interface, cujo código fonte é este, representa o serviço com a capacidade de mostrar o ecrã do mercado, para avaliar a aplicação. A implementação é MarketplaceReviewService.

IShareLinkService interface, cujo código fonte é este, representa o serviço com a capacidade para partilhar links na rede social, configuradas no dispositivo. A implementação é ShareLinkService.

IApplicationManifest interface, cujo código fonte é esterepresenta o serviço com a capacidade para ler a informação do ficheiro Manifest. A implementação é ApplicationManifestService.

Cada interface é injetada na View Model, que são definidas no ViewModelLocator. Por exemplo, para o caso do NavigationService vamos precisar definir:

SimpleIoc.Default.Register<INavigationService, NavigationService>();

Isto significa que, quando o Ioc container precisa da implementação do INavigationService, irá criar um objeto do tipo NavigationService. (A ideia é igual para as outras dependências)

Assim como vimos no HomeViewModel, cada botão da ApplicationBar irá ser binding a um comando que está associado a uma acção.


Veremos agora como aplicamos o nome do Author.

AboutPageBindingAutor.png

A propriedade Text da textBlock é binding à propriedade Author do AboutViewModel e esta propriedade irá obter o nome do Author definido no ficheiro Manifest. Não existe uma implementação direta para obter isto, mas com o uso da ApplicationManifest do Cimbalino toolkit não precisamos de nos preocupar com isso, porque esta classe tem esta funcionalidade implementada.

O valor da Version é aplicado da mesma forma que o Author.

ViewModelLocator.cs

Para ajudar na coneção da página com a sua view model, iremos usar o ViewModelLocator.

namespace NokiaDev.AboutPageSample.ViewModels
{
using Cimbalino.Phone.Toolkit.Services;
 
using GalaSoft.MvvmLight.Ioc;
 
using Microsoft.Practices.ServiceLocation;
 
/// <summary>
/// The view model locator.
/// </summary>
public class ViewModelLocator
{
/// <summary>
/// Initializes a new instance of the <see cref="ViewModelLocator"/> class.
/// </summary>
public ViewModelLocator()
{
// starts the Ioc container
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
 
// register all dependecies
if (!SimpleIoc.Default.IsRegistered<INavigationService>())
{
SimpleIoc.Default.Register<INavigationService, NavigationService>();
}
 
if (!SimpleIoc.Default.IsRegistered<IMarketplaceReviewService>())
{
SimpleIoc.Default.Register<IMarketplaceReviewService, MarketplaceReviewService>();
}
 
if (!SimpleIoc.Default.IsRegistered<IShareLinkService>())
{
SimpleIoc.Default.Register<IShareLinkService, ShareLinkService>();
}
 
if (!SimpleIoc.Default.IsRegistered<IApplicationManifestService>())
{
SimpleIoc.Default.Register<IApplicationManifestService, ApplicationManifestService>();
}
 
if (!SimpleIoc.Default.IsRegistered<IEmailComposeService>())
{
SimpleIoc.Default.Register<IEmailComposeService, EmailComposeService>();
}
 
// register all view models
SimpleIoc.Default.Register<HomeViewModel>();
 
SimpleIoc.Default.Register<AboutViewModel>();
}
 
/// <summary>
/// Gets the home view model.
/// </summary>
public HomeViewModel HomeViewModel
{
get
{
return ServiceLocator.Current.GetInstance<HomeViewModel>();
}
}
 
/// <summary>
/// Gets the about view model.
/// </summary>
public AboutViewModel AboutViewModel
{
get
{
return ServiceLocator.Current.GetInstance<AboutViewModel>();
}
}
 
/// <summary>
/// The cleanup.
/// </summary>
public static void Cleanup()
{
// TODO Clear the ViewModels
}
}
}

No construtor do ViewModelLocator iniciamos o Ioc container (SimpleIoc) e registamos todas as dependências e View Models. Este Ioc container gere todas as dependências e injeta cada uma nas view models. O ViewModelLocator contém uma propriedade para cada view model registado, sendo esta propriedade usada no binding com o a propriedade DataContextr da página.

Note.pngNote: A razão pela qual se verifica se cada dependência está registada, tem a ver com erros em modo de desenho no Visual Studio:

  if (!SimpleIoc.Default.IsRegistered<  ....  >())
{...}
Sem isto, cada dependência será registada duas vezes o que lança uma Exception .

O ViewModelLocator será adicionado ao App.xaml, que veremos de seguida.

App.xaml

O App é uma classe criada quando a aplicação inicia. Em XAML, é possível adicionar dicionários de resources ou mesmos simples objetos. Para o nosso exemplo, iremos adicionar o objeto ViewModelLocator que será estático.

<Application 
x:Class="NokiaDev.AboutPageSample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:viewModel="clr-namespace:NokiaDev.AboutPageSample.ViewModels">
 
<!--Application Resources-->
<Application.Resources>
<viewModel:ViewModelLocator x:Key="Locator" />
</Application.Resources>
 
<Application.ApplicationLifetimeObjects>
<!--Required object that handles lifetime events for the application-->
<shell:PhoneApplicationService
Launching="ApplicationLaunching" Closing="ApplicationClosing"
Activated="ApplicationActivated" Deactivated="ApplicationDeactivated"/>
</Application.ApplicationLifetimeObjects>
</Application>

Benefícios do padrão MVVM

Este tipo de implementação é muito importante, destacando-se os seguintes pontos:

* 	A implementação do view model é independente da implementação de cada serviço (ApplicationManifestService, NavigationService , etc). Apenas temos de respeitar a implementação da interface, podendo o comportamento ser alterável, e sem afetar o resto do código. 
*  	Desta forma podes implementar testes unitários para cada view model, usando serviços falsos. 
*  	O índice de manutenção é maior. 
*  	Os conceitos, funcionalidades ficam separados da e obtemos um código mais limpo. 
*  	Cada vez que a interface com o utilizador é alterado, apenas é preciso alterar o XAML, mas todo o comportamento se mantém (supondo claro que as funcionalidades se mantém).

Cada toolkit em causa é utilizador por várias pessoas, permitindo que sejam corridos erros e permite um rápido desenvolvimento. Se por alguma razão quisermos remover estas dependências, apenas temos que implementar as nossas interfaces e implementações. Não implicando isto que a aplicação seja toda rescrita.


Reutilizando a página Acerca de

Para cada aplicação que desenvolvemos, precisamos de ter um página "Acerca de", que de uma forma geral são iguais. Para simplificar o nosso desenvolvimento, devemos reutilizar este trabalho através da

  1. Criação de item templates para AboutPage.xaml e para AboutViewModel.cs
  2. Criação de project template para o projeto, permitindo a escolha da target pretendida.

Por causa do nosso projeto ter dependências de referências externas (Cimbalino Windows Phone Toolkit , MVVM Light Toolkit (PCL version)) e de imagens contidas na pasta de imagens, a segunda opção (criar o project template) é a melhor opção. Esta solução será discutida de seguida.

  1. Exportação do Template
    Selecionando a opção "Export Template".
    "Export Template Wizard" - Selecionando o Project Template para o projeto "NokiaDev.AboutPageSample.WP7.MVVM"
    Definindo os detalhes do novo Template.
    O *.zip resultante da exportação
  2. Edição do template exportado
    Depois de fazer "unzip" o ficheiro resultante, encontramos alguns ficheiros, *.cs and *.xaml comuns para nós, os quais reconhecemos. Mas existe um ficheiro importante com a extensão .vstemplate (normalmente renomeado para MyTemplate.vstemplate), o qual contém as definições para o projeto quando este é criado. De seguida podemos ver a versão inicial do ficheiro, com definições genéricas que serão alteradas na criação do projeto.
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
<TemplateData>
<Name>NokiaDev Windows Phone Application</Name>
<Description>A project for creating Windows Phone application with support for MVVM and About Page.</Description>
<ProjectType>CSharp</ProjectType>
<ProjectSubType>
</ProjectSubType>
<SortOrder>1000</SortOrder>
<CreateNewFolder>true</CreateNewFolder>
<DefaultName>NokiaDev Windows Phone Application</DefaultName>
<ProvideDefaultName>true</ProvideDefaultName>
<LocationField>Enabled</LocationField>
<EnableLocationBrowseButton>true</EnableLocationBrowseButton>
<Icon>__TemplateIcon.ico</Icon>
</TemplateData>
<TemplateContent>
<Project TargetFileName="NokiaDev.AboutPageSample.csproj" File="NokiaDev.AboutPageSample.csproj" ReplaceParameters="true">
<ProjectItem ReplaceParameters="true" TargetFileName="App.xaml">App.xaml</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="App.xaml.cs">App.xaml.cs</ProjectItem>
<ProjectItem ReplaceParameters="false" TargetFileName="ApplicationIcon.png">ApplicationIcon.png</ProjectItem>
<ProjectItem ReplaceParameters="false" TargetFileName="Background.png">Background.png</ProjectItem>
<Folder Name="Images" TargetFolderName="Images">
<ProjectItem ReplaceParameters="false" TargetFileName="appbar.about.png">appbar.about.png</ProjectItem>
<ProjectItem ReplaceParameters="false" TargetFileName="appbar.email.png">appbar.email.png</ProjectItem>
<ProjectItem ReplaceParameters="false" TargetFileName="appbar.rate.png">appbar.rate.png</ProjectItem>
<ProjectItem ReplaceParameters="false" TargetFileName="appbar.reply.email.png">appbar.reply.email.png</ProjectItem>
<ProjectItem ReplaceParameters="false" TargetFileName="appbar.share.png">appbar.share.png</ProjectItem>
<ProjectItem ReplaceParameters="false" TargetFileName="appbar.share.settings.png">appbar.share.settings.png</ProjectItem>
</Folder>
<ProjectItem ReplaceParameters="true" TargetFileName="packages.config">packages.config</ProjectItem>
<Folder Name="Properties" TargetFolderName="Properties">
<ProjectItem ReplaceParameters="true" TargetFileName="AppManifest.xml">AppManifest.xml</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="AssemblyInfo.cs">AssemblyInfo.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="WMAppManifest.xml">WMAppManifest.xml</ProjectItem>
</Folder>
<ProjectItem ReplaceParameters="true" TargetFileName="Read-Me.txt">Read-Me.txt</ProjectItem>
<ProjectItem ReplaceParameters="false" TargetFileName="Settings.StyleCop">Settings.StyleCop</ProjectItem>
<ProjectItem ReplaceParameters="false" TargetFileName="SplashScreenImage.jpg">SplashScreenImage.jpg</ProjectItem>
<Folder Name="ViewModels" TargetFolderName="ViewModels">
<ProjectItem ReplaceParameters="true" TargetFileName="AboutViewModel.cs">AboutViewModel.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="HomeViewModel.cs">HomeViewModel.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="ViewModelLocator.cs">ViewModelLocator.cs</ProjectItem>
</Folder>
<Folder Name="Views" TargetFolderName="Views">
<ProjectItem ReplaceParameters="true" TargetFileName="AboutPage.xaml">AboutPage.xaml</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="AboutPage.xaml.cs">AboutPage.xaml.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="HomePage.xaml">HomePage.xaml</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="HomePage.xaml.cs">HomePage.xaml.cs</ProjectItem>
</Folder>
</Project>
</TemplateContent>
</VSTemplate>

Note.pngNote: TemplateData contém todas as definições do template e TemplateContent contém todas as pastas e ficheiros que serão adicionados ao projeto na sua criação.

  1. Template foldercontent.png

    Tip.pngTip: É preciso adicionar os ficheiros nupkg (Cimbalino.Phone.Toolkit.2.1.nupkg, Portable.MvvmLightLibs.4.1.27.1.nupkg, Unofficial.Blend.Interactivity.1.0.0.nupkg e Portable.CommonServiceLocator.1.2.2.nupkg) que serão usados na instalação dos NuGet packages usados no projeto. E é preciso adicionar referências a estes ficheiros no final do ficheiro *.vstemplate.

    <VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
    .....
    <WizardExtension>
    <Assembly>NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly>
    <FullClassName>NuGet.VisualStudio.TemplateWizard</FullClassName>
    </WizardExtension>
    <WizardData>
    <packages repository="template">
    <package id="Cimbalino.Phone.Toolkit" version="2.1" targetFramework="wp71" />
    <package id="Portable.CommonServiceLocator" version="1.2.2" targetFramework="wp71" />
    <package id="Portable.MvvmLightLibs" version="4.1.27.1" targetFramework="wp71" />
    <package id="Unofficial.Blend.Interactivity" version="1.0.0" targetFramework="wp71" />
    </packages>
    </WizardData>
    </VSTemplate>

  2. Adição do novo template, para instalação. O template deve ficar junto do templates de Windows Phone, por esta razão foi adicionado a uma pasta com o nome Windows Phone.
    Template folderInstall.png

    Tip.pngTip: O ficheiro *.vstemplate deve estar contido na raíz da pasta *zip, senão o template não irá aparecer na lista de templates.

  3. Instalação do novo template
    Template install.png


O template resultante é: NokiaDev - Windows Phone Template

O template foi criado para Windows Phone SO 7.1 e pode ser atualizado para Windows Phone SO 8.0. A boa prática sobre isto, mas fora do âmbito do artigo, será criar um IWizard que irá apresentar uma interface para selecionar a target do projeto aquando da sua criação.

Tip.pngTip: Item e Project templates podem ser encontrados nas seguintes pastas. Note-se que alterações nestas pastas podem causar problemas ao executar o Visual Studio.

  • Item Templates podem ser encontrados em "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ItemTemplates\"
  • Project Template podem ser encontrados em "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ProjectTemplates\"
Os nossos Item Templates ou Project Template devem ser adicionados em C:\Users\{USERNAME}\Documents\Visual Studio 2012\Templates

Referências:

Nota: (*) Artigos disponível, apenas, em Inglês.


Conclusão

Em conclusão, uma página Sobre mantém o utilizador informado sobre os detalhes mais importantes da aplicação. E permite adicionar funcionalidades como a avaliação, feedback e partilha, que aumentam a qualidade da mesma, podendo ser um bom meio de marketing. A opinião do utilizador é o melhor feedback que podemos ter para podermos ter uma aplicação de sucesso, por esta razão é recomendável que cada aplicação tenha uma.

Para garantir um desenvolvimento rápido em tarefas, que de uma forma geral são, repetidas devemos reutilizar o código criado.

Referências adicionais

Os seguintes artigos foram escritos algum tempo atrás. O código poderá estar desatualizado mas a ideia poderá ser analisada:

Nota: (*) Artigos disponível, apenas, em Inglês.

This page was last modified on 5 November 2013, at 12:46.
212 page views in the last 30 days.
×