Parte 5: criar um leitor de blog (aplicativos da Windows Store em C#/VB e XAML)

Parte 5: criar um leitor de blog (aplicativos da Windows Store em C#/VB e XAML)

[ Este artigo destina-se aos desenvolvedores do Windows 8.x e do Windows Phone 8.x que escrevem aplicativos do Windows Runtime. Se você estiver desenvolvendo para o Windows 10, consulte documentação mais recente ]

Introduzimos os códigos e os conceitos essenciais necessários para criar um aplicativo da Windows Store em C# ou Visual Basic. Você usará XAML para definir a interface do usuário e a linguagem de sua preferência para escrever a lógica do aplicativo.

Importante   Este tutorial deve ser usado com o Microsoft Visual Studio 2012 e o Windows 8. Partes dele não funcionarão corretamente no Microsoft Visual Studio 2013 e no Windows 8.1.
 

Se preferir usar outra linguagem de programação, confira:

Mapa: como este tópico está relacionado aos outros? Consulte: Mapa de aplicativos da Windows Store em C# ou Visual Basic .

Antes de começar...

Objetivos

Neste tutorial, faremos um rápido tour pelos recursos que você usará para construir aplicativos da Windows Store. Durante o processo de criação de um aplicativo leitor de blog simples, apresentamos conceitos que são essenciais para o desenvolvimento com XAML, incluindo layout, controles, modelos e vinculação de dados. Você aprende como usar os modelos e a navegação de página que são integrados ao Microsoft Visual Studio Express 2012 para Windows 8 para iniciar rapidamente o desenvolvimento do aplicativo. Depois aprende como usar estilos personalizados para modificar a aparência do aplicativo e como adaptar a interface do usuário a diversos layouts e modos de exibição. Por fim, discutimos brevemente a integração do aplicativo com o Windows 8 e sua publicação na Windows Store. Ao concluir este tutorial, você estará preparado para começar a montar seus próprios aplicativos da Windows Store.

Hello World

Ao criar seu aplicativo da Windows Store em C# ou Visual Basic, você geralmente define a interface do usuário usando XAML e cria a lógica do aplicativo em um arquivo code-behind associado, no idioma selecionado. A estrutura da IU em XAML para aplicativos da Windows Store que usam C# ou Visual Basic está nos namespaces Windows.UI.Xaml.* do Tempo de Execução do Windows. Se tiver criado aplicativos usando o WPF (Windows Presentation Foundation), o Microsoft Silverlight ou o Silverlight para Windows Phone, esse modelo de programação não será novidade e você poderá usar essa experiência para criar seu aplicativo da Windows Store em C# ou Visual Basic.

O exemplo aqui mostra o XAML que define a interface do usuário para um aplicativo "Hello, world" simples e sua página code-behind associada. Mesmo este exemplo simples mostra diversos conceitos que são importantes para o modelo de programação baseado em XAML, incluindo classes parciais, layouts, controles, propriedades e eventos.



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

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel>
            <Button Content="Click Me" Click="HelloButton_Click" />
            <TextBlock x:Name="DisplayText" FontSize="48" />
        </StackPanel>
    </Grid>
</Page>



using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace WindowsBlogReader
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void HelloButton_Click(object sender, RoutedEventArgs e)
        {
            DisplayText.Text = "Hello, world";
        }
    }
}

Um aplicativo "Hello, world" é um bom local para começar. Mas isso não nos leva muito longe, portanto, vamos seguir um caminho diferente à medida que exploramos a criação de aplicativos da Windows Store. O aplicativo de exemplo que você usa para começar é um leitor de blog simples, que baixa e exibe dados de um feed RSS 2.0 ou Atom 1.0. Vamos usar os feeds do site de blogs da equipe do Windows. Uma vez terminado, o aplicativo será parecido com este:

Exemplo de navegação de três páginas.

Criando aplicativos da Windows Store no Visual Studio

Nesta seção, você aprenderá como:

  • criar um novo projeto de aplicativo da Windows Store no Visual Studio Express 2012 para Windows 8.

O Visual Studio é um Ambiente de Desenvolvimento Integrado (IDE, Integrated Development Environment) avançado para desenvolver aplicativos do Windows. Ele fornece o gerenciamento de arquivos de origem; compilação integrada, suporte para implantação e lançamento; XAML, Visual Basic, C#, C++, gráficos e edição de manifesto; depuração e muito mais. O Visual Studio vem em diversas edições, mas você usará o Visual Studio Express 2012 para Windows 8. Você pode baixá-lo gratuitamente junto com o Software Development Kit do Windows (SDK do Windows) para Windows 8, para ter tudo de que precisa para compilar, empacotar e implantar aplicativos da Windows Store.

Para começar a criar um aplicativo, crie um novo projeto da Windows Store em C# ou Visual Basic. O Visual Studio Express 2012 RC para Windows 8 inclui diversos modelos para projetos da Windows Store que dão uma visão geral sobre aplicativos que usam diversos layouts. O modelo de projeto de Aplicativo em Branco (XAML) fornece os arquivos mínimos necessários para qualquer aplicativo da Windows Store.

BR211380.wedge(pt-br,WIN.10).gifPara criar um novo projeto da Windows Store

  1. Abra o Visual Studio Express 2012 para Windows 8.
  2. Selecione Arquivo > Novo Projeto. A caixa de diálogo Novo Projeto é aberta.
  3. Na seção Modelos do painel esquerdo, expanda Visual C# ou Visual Basic.
  4. Selecione o tipo de modelo da Windows Store.
  5. No painel central, selecione Aplicativo em Branco (XAML).
  6. Digite um nome para o projeto. Dê um nome para o projeto "WindowsBlogReader".

    Veja a seguir um novo projeto sendo criado no Visual Studio Express 2012 para Windows 8.

    Caixa de diálogo Novo Projeto do Visual Studio.

  7. Clique em OK. Os arquivos do seu projeto são criados.

Quando você cria seu projeto, o Visual Studio cria os arquivos do projeto e os exibe no Gerenciador de Soluções. Vejamos as pastas e os arquivos que o modelo Aplicativo em Branco (XAML) criou.

Nome do arquivoDescrição
Properties/AssemblyInfo (.vb or .cs)Contém os metadados de nome e versão incorporados ao conjunto gerado.
Package.appxmanifestContém metadados que descrevem o aplicativo, inclusive nome para exibição, descrição, logotipos e recursos.
Assets/* As imagens de tela inicial e logotipo padrão que você pode substituir pelas suas próprias imagens.
Common/StandardStyles.xamlContém estilos e modelos padrão para o aplicativo.
App.xaml, App.xaml.cs/vb Estes arquivos especificam a lógica no nível do aplicativo. A classe App é necessária para exibir a interface do usuário.
MainPage.xamlA página inicial padrão usada para criar a interface do usuário.
MainPage.xaml.cs/vbO arquivo code-behind que contém a lógica para a página inicial padrão.

 

Obtendo dados em um aplicativo

Nesta seção, você aprenderá como:

  • criar uma classe de dados personalizada
  • recuperar um feed de dados RSS ou Atom de forma assíncrona.

Antes de criar a interface de usuário do aplicativo, você escreve o código para obter os dados de feed de blog a fim de ter algo para mostrar na interface. Os blogs da equipe do Windows expõem o texto completo das postagens nos formatos RSS e Atom. Os dados de blog que você deseja exibir no aplicativo leitor são: título, autor, data e conteúdo de cada uma das postagens mais recentes.

Para começar, você precisa baixar os dados de cada uma das postagens. Felizmente, o Tempo de Execução do Windows contém um conjunto de classes que faz grande parte do trabalho de processamento dos dados de feed para você. Essas classes são encontradas no namespace Windows.Web.Syndication e podem ser usadas diretamente para mostrar os dados na interface do usuário. Mas, no leitor de blog, você cria suas próprias classes de dados. Isso proporciona certa flexibilidade adicional e permite tratar feeds RSS e Atom da mesma forma.

Você usa 3 classes para reter e recuperar os dados de feed no aplicativo leitor de blog. Todas elas são colocadas em um arquivo chamado FeedData.cs/vb. A classe FeedData contém informações sobre o feed RSS ou Atom. A classe FeedItem contém informações sobre postagens de blog individuais pertencentes ao feed. A classe FeedDataSource contém uma coleção de feeds e um método para recuperar os feeds da rede.

BR211380.wedge(pt-br,WIN.10).gifPara adicionar classes de dados ao projeto

  1. Selecione Projeto > Adicionar Classe. A caixa de diálogo Novo Item é aberta.
  2. Digite "FeedData" como o nome do arquivo de classe.
  3. Clique em Adicionar. Seu novo arquivo de classe será criado.
  4. Copie este código para o arquivo FeedData.cs/vb. Substitua qualquer código que esteja no arquivo.
    
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Threading.Tasks;
    using Windows.Web.Syndication;
    
    namespace WindowsBlogReader
    {
        // FeedData
        // Holds info for a single blog feed, including a list of blog posts (FeedItem).
        public class FeedData
        {
            public string Title { get; set; }
            public string Description { get; set; }
            public DateTime PubDate { get; set; }
    
            private List<FeedItem> _Items = new List<FeedItem>();
            public List<FeedItem> Items
            {
                get
                {
                    return this._Items;
                }
            }
        }
    
        // FeedItem
        // Holds info for a single blog post.
        public class FeedItem
        {
            public string Title { get; set; }
            public string Author { get; set; }
            public string Content { get; set; }
            public DateTime PubDate { get; set; }
            public Uri Link { get; set; }
        }
    
        // FeedDataSource
        // Holds a collection of blog feeds (FeedData), and contains methods needed to
        // retreive the feeds.
        public class FeedDataSource
        {
            private ObservableCollection<FeedData> _Feeds = new ObservableCollection<FeedData>();
            public ObservableCollection<FeedData> Feeds
            {
                get
                {
                    return this._Feeds;
                }
            }
    
            public async Task GetFeedsAsync()
            {
                Task<FeedData> feed1 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/developers/atom.aspx");
                Task<FeedData> feed2 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx");
                Task<FeedData> feed3 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/extremewindows/atom.aspx");
                Task<FeedData> feed4 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/business/atom.aspx");
                Task<FeedData> feed5 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx");
                Task<FeedData> feed6 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/windowssecurity/atom.aspx");
                Task<FeedData> feed7 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/springboard/atom.aspx");
                Task<FeedData> feed8 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/windowshomeserver/atom.aspx");
                // There is no Atom feed for this blog, so use the RSS feed.
                Task<FeedData> feed9 =
                    GetFeedAsync("http://windowsteamblog.com/windows_live/b/windowslive/rss.aspx");
                Task<FeedData> feed10 =
                    GetFeedAsync("http://windowsteamblog.com/windows_live/b/developer/atom.aspx");
                Task<FeedData> feed11 =
                    GetFeedAsync("http://windowsteamblog.com/ie/b/ie/atom.aspx");
                Task<FeedData> feed12 =
                    GetFeedAsync("http://windowsteamblog.com/windows_phone/b/wpdev/atom.aspx");
                Task<FeedData> feed13 =
                    GetFeedAsync("http://windowsteamblog.com/windows_phone/b/wmdev/atom.aspx");
                Task<FeedData> feed14 =
                    GetFeedAsync("http://windowsteamblog.com/windows_phone/b/windowsphone/atom.aspx");
    
                this.Feeds.Add(await feed1);
                this.Feeds.Add(await feed2);
                this.Feeds.Add(await feed3);
                this.Feeds.Add(await feed4);
                this.Feeds.Add(await feed5);
                this.Feeds.Add(await feed6);
                this.Feeds.Add(await feed7);
                this.Feeds.Add(await feed8);
                this.Feeds.Add(await feed9);
                this.Feeds.Add(await feed10);
                this.Feeds.Add(await feed11);
                this.Feeds.Add(await feed12);
                this.Feeds.Add(await feed13);
                this.Feeds.Add(await feed14);
            }
    
            private async Task<FeedData> GetFeedAsync(string feedUriString)
            {
                Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
                Uri feedUri = new Uri(feedUriString);
    
                try
                {
                    SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);
    
                    // This code is executed after RetrieveFeedAsync returns the SyndicationFeed.
                    // Process the feed and copy the data you want into the FeedData and FeedItem classes.
                    FeedData feedData = new FeedData();
    
                    if (feed.Title != null && feed.Title.Text != null)
                    {
                        feedData.Title = feed.Title.Text;
                    }
                    if (feed.Subtitle != null && feed.Subtitle.Text != null)
                    {
                        feedData.Description = feed.Subtitle.Text;
                    }
                    if (feed.Items != null && feed.Items.Count > 0)
                    {
                        // Use the date of the latest post as the last updated date.
                        feedData.PubDate = feed.Items[0].PublishedDate.DateTime;
    
                        foreach (SyndicationItem item in feed.Items)
                        {
                            FeedItem feedItem = new FeedItem();
                            if (item.Title != null && item.Title.Text != null)
                            {
                                feedItem.Title = item.Title.Text;
                            }
                            if (item.PublishedDate != null)
                            {
                                feedItem.PubDate = item.PublishedDate.DateTime;
                            }
                            if (item.Authors != null && item.Authors.Count > 0)
                            {
                                feedItem.Author = item.Authors[0].Name.ToString();
                            }
                            // Handle the differences between RSS and Atom feeds.
                            if (feed.SourceFormat == SyndicationFormat.Atom10)
                            {
                                if (item.Content != null && item.Content.Text != null)
                                {
                                    feedItem.Content = item.Content.Text;
                                }
                                if (item.Id != null)
                                {
                                    feedItem.Link = new Uri("http://windowsteamblog.com" + item.Id);
                                }
                            }
                            else if (feed.SourceFormat == SyndicationFormat.Rss20)
                            {
                                if (item.Summary != null && item.Summary.Text != null)
                                {
                                    feedItem.Content = item.Summary.Text;
                                }
                                if (item.Links != null && item.Links.Count > 0)
                                {
                                    feedItem.Link = item.Links[0].Uri;
                                }
                            }
                            feedData.Items.Add(feedItem);
                        }    
                    }
                    return feedData;
                }
                catch (Exception)
                {
                    return null;
                }
            }
    
            // Returns the feed that has the specified title.
            public static FeedData GetFeed(string title)
            {
                // Simple linear search is acceptable for small data sets
                var _feedDataSource = App.Current.Resources["feedDataSource"] as FeedDataSource;
    
                var matches = _feedDataSource.Feeds.Where((feed) => feed.Title.Equals(title));
                if (matches.Count() == 1) return matches.First();
                return null;
            }
    
            // Returns the post that has the specified title.
            public static FeedItem GetItem(string uniqueId)
            {
                // Simple linear search is acceptable for small data sets
                var _feedDataSource = App.Current.Resources["feedDataSource"] as FeedDataSource;
                var _feeds = _feedDataSource.Feeds;
    
                var matches = _feedDataSource.Feeds.SelectMany(group => group.Items).Where((item) => item.Title.Equals(uniqueId));
                if (matches.Count() == 1) return matches.First();
                return null;
            }
        }
    }
    
    
  5. Clique em Compilar > Compilar solução para garantir que a solução seja compilada sem erros.

Recuperando os dados do feed

Vamos examinar melhor como os feeds de blog são baixados. A classe Windows.Web.Syndication.SyndicationClient recupera um feed RSS ou Atom completamente analisado, então você pode usar os dados sem se preocupar em analisar o XML. Para baixar um feed usando a classe SyndicationClient, é preciso usar o método RetrieveFeedAsync assíncrono. O modelo de programação assíncrono é comum no Tempo de Execução do Windows para ajudar os aplicativos a permanecerem responsivos. Felizmente, grande parte da complexidade que você poderia esperar ao usar métodos assíncronos já foi controlada.

Usando a espera em C# e Visual Basic

Usando a palavra-chave await em C# e Visual Basic, o código para recuperar o feed de forma assíncrona é semelhante ao que seria usado para recuperar o feed de forma síncrona. Vamos dar uma olhada.

No método GetFeedsAsync, você chama GetFeedAsync para cada um dos feeds de blog que deseja recuperar. Onde possível, você passa a URL do feed Atom, porque ele inclui dados do autor que você quer exibir. Se não houver nenhum feed Atom, use o RSS feed. Quando cada feed de blog é retornado, você o adiciona à coleção FeedDataSource.Feeds.

Para fazer isso usando métodos síncronos, o código pode ser parecido com este. Aqui, o método GetFeed retorna um objeto FeedData. Quando o FeedData é retornado, é adicionado à coleção de Feeds.



public void GetFeeds()
{
    FeedData feed1 = 
        GetFeed("http://windowsteamblog.com/windows/b/developers/atom.aspx");
    ...
    this.Feeds.Add(feed1);
    ...
}

Agora vamos ver como fazer isso usando métodos "async" e ver como a palavra-chave await ajuda. A primeira coisa a observar é que você adiciona a palavra-chave async à assinatura do método. A palavra-chave await só pode ser usada em um método definido como async. Você especifica o tipo de retorno de GetFeedsAsync como Task.



public async Task GetFeedsAsync()
{
    Task<FeedData> feed1 = 
        GetFeedAsync("http://windowsteamblog.com/windows/b/developers/atom.aspx");
    ...
    this.Feeds.Add(await feed1);
    ...
}

No código async, o método GetFeedAsync retorna uma Task<FeedData>, ou Task(Of FeedData) no VB, que representa o FeedData que no final será o valor de retorno do método.

Neste ponto do código:


this.Feeds.Add(await feed1);

a chamada a GetFeedAsync é feita e uma Task<FeedData> é retornada. A próxima linha de código é executada (para obter feed2), mas feed1 não será adicionado à coleção de Feeds até que o objeto FeedData seja realmente passado à Task<FeedData> que o aguarda. Voltamos a isso em breve. Agora vejamos o que acontece no método GetFeedAsync.

Você especifica o tipo de retorno de GetFeedAsync como Task<FeedData>. Isso informa ao compilador para gerar um Task que represente o objeto FeedData recuperado pelo método.


private async Task<FeedData> GetFeedAsync(string feedUriString)
{
...
}

Dentro do método, você cria uma instância de SyndicationClient e chama o respectivo método RetrieveFeedAsync para obter o SyndicationFeed que contém as informações de RSS ou Atom desejadas.


Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
Uri feedUri = new Uri(feedUriString);
...
    SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);

Como RetrieveFeedAsync é um método assíncrono, você usa a palavra-chave await novamente. A palavra-chave await informa ao compilador para executar grande parte do trabalho automaticamente em segundo plano. O compilador programa o restante do método após essa chamada como um retorno de chamada a ser executado quando a chamada retornar. Então, ele retorna imediatamente o controle para o thread de chamada, geralmente o thread de interface do usuário, para que o aplicativo permaneça responsivo. O Task<FeedData> que representa o resultado eventual desse método, um objeto FeedData, é retornado para o chamador neste ponto.

Quando o RetrieveFeedAsync retorna o SyndicationFeed com os dados desejados, o restante do código no método é executado. E, principalmente, é executado no mesmo contexto de thread do qual você fez a chamada original (o thread de interface do usuário); portanto, não é preciso se preocupar em usar um dispatcher para atualizar a interface do usuário nesse código. Com o SyndicationFeed recuperado, você copia as partes de que precisa em suas classes de dados FeedData e FeedItem.



// This code is executed after RetrieveFeedAsync returns the SyndicationFeed.
// Process the feed and copy the data you want into the FeedData and FeedItem classes.
FeedData feedData = new FeedData();

if (feed.Title != null && feed.Title.Text != null)
{
    feedData.Title = feed.Title.Text;
}
if (feed.Subtitle != null && feed.Subtitle.Text != null)
{
    feedData.Description = feed.Subtitle.Text;
}
if (feed.Items != null && feed.Items.Count > 0)
{
    // Use the date of the latest post as the last updated date.
    feedData.PubDate = feed.Items[0].PublishedDate.DateTime;

    foreach (SyndicationItem item in feed.Items)
    {
        FeedItem feedItem = new FeedItem();
        if (item.Title != null && item.Title.Text != null)
        {
            feedItem.Title = item.Title.Text;
        }
        if (item.PublishedDate != null)
        {
            feedItem.PubDate = item.PublishedDate.DateTime;
        }
        if (item.Authors != null && item.Authors.Count > 0)
        {
            feedItem.Author = item.Authors[0].Name.ToString();
        }
        // Handle the differences between RSS and Atom feeds.
        if (feed.SourceFormat == SyndicationFormat.Atom10)
        {
            if (item.Content != null && item.Content.Text != null)
            {
                feedItem.Content = item.Content.Text;
            }
            if (item.Id != null)
            {
                feedItem.Link = new Uri("http://windowsteamblog.com" + item.Id);
            }
        }
        else if (feed.SourceFormat == SyndicationFormat.Rss20)
        {
            if (item.Summary != null && item.Summary.Text != null)
            {
                feedItem.Content = item.Summary.Text;
            }
            if (item.Links != null && item.Links.Count > 0)
            {
                feedItem.Link = item.Links[0].Uri;
            }
        }
        feedData.Items.Add(feedItem);
    }    
}
return feedData;

Quando o código chega à declaração return, ele não está realmente retornando no sentido como um método síncrono retorna. Lembre-se de que o método retornou para o chamador imediatamente após a declaração "await". Ele retornou uma Task<FeedData> para representar o resultado eventual do método. Aqui, você finalmente obtém o resultado. A linha return feedData; apresenta o objeto FeedData que é o resultado do método para a Task<FeedData> que está esperando por ele.

A Task era esperada nessa linha no método GetFeedsAsync.


this.Feeds.Add(await feed1);

Quando a Task obtém o resultado FeedData que está esperando, a execução do código prossegue e o FeedData é adicionado à coleção FeedDataSource.Feeds.

Usando os dados no aplicativo

Para usar os dados no aplicativo, você cria uma instância da fonte de dados como um recurso no App.xaml, dando a ela o nome de feedDataSource.

BR211380.wedge(pt-br,WIN.10).gifPara adicionar um recurso a um aplicativo

  1. Clique duas vezes no App.xaml, no Gerenciador de Soluções. O arquivo é aberto no editor de XAML.
  2. Adicione a declaração de recurso, <local:FeedDataSource x:Key="feedDataSource"/>, ao ResourceDictionary raiz após a coleção MergedDictionaries.

Este é o XAML completo para a seção Application.Resources depois que você adiciona um novo recurso.


    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- 
                    Styles that define common aspects of the platform look and feel
                    Required by Visual Studio project and item templates
                 -->
                <ResourceDictionary Source="Common/StandardStyles.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            
            <local:FeedDataSource x:Key="feedDataSource"/>
        </ResourceDictionary>
    </Application.Resources>

Para recuperar os feeds, adicione código à substituição do método OnLaunched no arquivo App.xaml.cs/vb. Esse método é executado sempre que um usuário inicia o aplicativo.

Aqui você adiciona a palavra-chave async à declaração do método porque usa a palavra-chave await dentro do método. Como o aplicativo requer uma conexão ativa com a Internet para baixar feeds, você usa a classe NetworkInformation para verificar se há uma conexão. Se o aplicativo estiver conectado, você baixa os feeds; caso contrário, notifica o usuário. Você adiciona código para obter a instância de FeedDataSource do aplicativo e verificar se ela já contém feeds. Caso não contenha, você chama o método FeedDataSource.GetFeedsAsync para recuperar os feeds.

BR211380.wedge(pt-br,WIN.10).gifPara obter os feeds

  1. Clique duas vezes no App.xaml.cs/vb, no Gerenciador de Soluções. O arquivo é aberto no editor de código.
  2. Adicione a palavra-chave async à assinatura do método OnLaunched.
    
    protected async override void OnLaunched(LaunchActivatedEventArgs args)
    
    
  3. Adicione este código ao método OnLaunched, imediatamente após a instanciação do novo Frame, rootFrame = New Frame().
    
                    // Add this code after "rootFrame = new Frame();"
                    var connectionProfile = Windows.Networking.Connectivity.NetworkInformation.GetInternetConnectionProfile();
                    if (connectionProfile != null)
                    {
                        FeedDataSource feedDataSource = (FeedDataSource)App.Current.Resources["feedDataSource"];
                        if (feedDataSource != null)
                        {
                            if (feedDataSource.Feeds.Count == 0)
                            {
                                await feedDataSource.GetFeedsAsync();
                            }
                        }
                    }
                    else
                    {
                        var messageDialog = new Windows.UI.Popups.MessageDialog("An internet connection is needed to download feeds. Please check your connection and restart the app.");
                        var result = messageDialog.ShowAsync();
                    }
    
    

Este é o código completo do método OnLaunched depois de você adicionar o código.


        protected async override void OnLaunched(LaunchActivatedEventArgs args)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                // Add this code after "rootFrame = new Frame();"
                var connectionProfile = Windows.Networking.Connectivity.NetworkInformation.GetInternetConnectionProfile();
                if (connectionProfile != null)
                {
                    FeedDataSource feedDataSource = (FeedDataSource)App.Current.Resources["feedDataSource"];
                    if (feedDataSource != null)
                    {
                        if (feedDataSource.Feeds.Count == 0)
                        {
                            await feedDataSource.GetFeedsAsync();
                        }
                    }
                }
                else
                {
                    var messageDialog = new Windows.UI.Popups.MessageDialog("An internet connection is needed to download feeds. Please check your connection and restart the app.");
                    var result = messageDialog.ShowAsync();
                }

                if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                if (!rootFrame.Navigate(typeof(ItemsPage), args.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
            }
            // Ensure the current window is active
            Window.Current.Activate();
        }

Você pode compilar e executar o aplicativo no modo de depuração para garantir que ele irá compilar e recuperar os feeds sem gerar erros. Se não houver erros, o aplicativo será executado, mas mostrará apenas uma tela em branco. Se houver algum erro, o Visual Studio apresentará informações sobre ele. Para saber mais sobre como executar aplicativos no Visual Studio, consulte Executando aplicativos da Windows Store no Visual Studio .

BR211380.wedge(pt-br,WIN.10).gifPara executar o aplicativo no modo de depuração

  1. Para executar o aplicativo, execute um destes procedimentos:
    • Clique em Depurar > Iniciar depuração.
    • Pressione F5.
  2. Para parar a depuração:
    1. Pressione Alt+Tab para voltar ao Visual Studio.
    2. No Visual Studio, execute um dos seguintes.
      • Clique em Depurar > Parar depuração.
      • Pressione Shift+F5.

Agora você cria a interface de usuário para mostrar os dados.

Adicionando páginas e navegação

Para mostrar os blogs da equipe do Windows, você precisa adicionar páginas ao aplicativo e manipular a navegação entre essas páginas. Primeiro, você quer uma página que liste todos os blogs da equipe do Windows. Quando um leitor seleciona um blog nessa página, você navega para uma nova página e carrega a lista de postagens desse blog. Também adiciona uma página de detalhes, para que um usuário possa ler postagens de blog individuais sem que a exibição de lista ocupe espaço.

Modelos de página

Felizmente, não é preciso criar cada página com base em um modelo em branco. O Visual Studio Express 2012 para Windows 8 vem com uma coleção de modelos de página que são úteis para diversas situações. Estes são os modelos de página disponíveis.

Tipo de páginaDescrição
Página de Detalhes do GrupoExibe detalhes de um único grupo e visualizações de cada item do grupo.
Página de Itens AgrupadosExibe coleções agrupadas.
Página de Detalhes do ItemExibe um item em detalhes e permite a navegação para itens adjacentes.
Página de ItensExibe uma coleção de itens.
Página DivididaExibe uma lista de itens e detalhes do item selecionado.
Página BásicaUma página vazia que pode se adaptar a diferentes orientações e modos de exibição. Ela possui um título e um botão Voltar.
Página em Branco Uma página em branco para um aplicativo da Windows Store.

 

Use o modelo de Página de Itens para mostrar a lista de blogs da equipe do Windows. Use o modelo de Página Dividida para mostrar as postagens de cada blog e o texto da postagem selecionada. Use o modelo de Página Básica para a página de detalhes.

BR211380.wedge(pt-br,WIN.10).gifPara adicionar páginas ao aplicativo

  1. Selecione Projeto > Adicionar Novo Item. A caixa de diálogo Adicionar Novo Item será aberta.

    Veja a caixa de diálogo Adicionar Novo Item.

    Caixa de diálogo Adicionar Novo Item do Visual Studio.
  2. Em Visual C# ou Visual Basic no painel esquerdo, selecione o tipo de modelo da Windows Store.
  3. No painel central, selecione o tipo de página a ser adicionada ao seu projeto. Selecione o modelo de Página de Itens.
  4. Insira um nome para a página. Insira "ItemsPage.xaml".
  5. Clique em Adicionar.

    Quando você adiciona uma página pela primeira vez ao modelo Aplicativo em Branco (que não seja uma Página em Branco), o Visual Studio mostra uma caixa de diálogo com uma mensagem informando que você precisa adicionar arquivos que estão ausentes no seu projeto. Clique em Sim para adicionar esses arquivos. Arquivos referentes a várias classes utilitárias serão adicionados ao seu projeto na pasta Comum.

    Os arquivos do XAML e de code-behind para a página são adicionados ao projeto.

  6. Clique em Compilar > Compilar solução para compilar o aplicativo. A nova página mostrará um erro no designer até você compilar as classes auxiliares das quais ela depende.
  7. Repita as etapas 1 a 5 para adicionar uma página dividida.
    • Na etapa 3, selecione o modelo de Página Dividida.
    • Na etapa 4, nomeie a página, "SplitPage.xaml".
  8. Repita as etapas 1 a 5 para adicionar uma página básica.
    • Na etapa 3, selecione o modelo de Página Básica.
    • Na etapa 4, nomeie a página, "DetailPage.xaml".

Quando você adiciona os modelos de página ao projeto e examina o XAML e o code-behind, é evidente que esses modelos cuidam de boa parte do trabalho. Na verdade, é fácil se perder, por isso vamos observar melhor os modelos de página e ver o que eles contêm. Todos os modelos de página XAML para os aplicativos da Windows Store possuem o mesmo formato.

O XAML para os modelos de página possui 3 seções principais:

Recursos Estilos e modelos de dados da página são definidos na seção Resources. Falaremos mais sobre isso na seção Criando uma aparência consistente com estilos.
Conteúdo do Aplicativo Os controles e conteúdo que formam a interface do usuário do aplicativo são definidos no painel de layout raiz.
Visual State Manager Animações e transições que adaptam o aplicativo a diferentes layouts e orientações são definidas na seção VisualStateManager. Falaremos mais sobre isso na seção Adaptando-se a diferentes layouts.

 

As páginas de modelo que você usa são todas derivadas da classe LayoutAwarePage e podem fazer muito mais por padrão do que a Página em Branco que é usada para o MainPage.xaml em um aplicativo Em Branco. LayoutAwarePage é uma implementação de Page que habilita uma funcionalidade importante para o desenvolvimento de aplicativo da Windows Store:

  • O mapeamento do estado da exibição do aplicativo para estado visual permite que a página se adapte a diferentes resoluções, orientações e exibições.
  • Os manipuladores de eventos GoBack e GoHome dão suporte à navegação básica.
  • Um modelo de página padrão oferece uma origem de dados vinculável simples.
  • Os métodos SaveState e LoadState funcionam com a classe SuspensionManager para gerenciar o estado da sessão do aplicativo.

Os modelos de página também permitem o uso de estilos e modelos encontrados em StandardStyles.xaml que aplicam as diretrizes de projeto para aplicativos da Windows Store. Você irá usar alguns desses estilos como ponto de partida e modificar cópias deles para personalizar a aparência do aplicativo.

Navegando entre as páginas

A estrutura da IU XAML oferece um modelo de navegação interno que usa Frames e Pages e funciona de maneira semelhante à navegação em um navegador da Web. O controle Frame hospeda Pages e tem um histórico de navegação que você pode usar para avançar e retroceder pelas páginas que visitou. Você pode transmitir dados entre páginas enquanto navega.

Navegando para ItemsPage

Nos modelos de projeto do Visual Studio, um Frame chamado rootFrame é definido como o conteúdo da janela do aplicativo. Esse Frame hospeda todas as Pages no aplicativo. Vamos examinar o código relevante em App.xaml.cs/vb.



        protected async override void OnLaunched(LaunchActivatedEventArgs args)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

               ...

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
            }
            // Ensure the current window is active
            Window.Current.Activate();
        }

Esse código obterá um Frame, se houver; caso contrário, ele criará um novo e o definirá como o conteúdo da janela. Depois, navegará para MainPage. Como você quer que a primeira página do aplicativo seja ItemsPage, é preciso alterar a chamada para o método Navigate e passar ItemsPage como a Page para a qual você vai navegar.

BR211380.wedge(pt-br,WIN.10).gifPara navegar para ItemsPage

  1. Clique duas vezes no App.xaml.cs/vb, no Gerenciador de Soluções. O arquivo é aberto no editor de código.
  2. No método OnLaunched, atualize a chamada para rootFrame.Navigate e passe ItemsPage como o primeiro parâmetro, como mostrado aqui.
    
    
                if (!rootFrame.Navigate(typeof(ItemsPage), args.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
    
    
    
  3. Pressione F5 para compilar e executar o aplicativo. Agora, a ItemsPage é carregada no lugar da MainPage.
    Observação   O arquivo MainPage.xaml padrão não é mais necessário neste projeto e pode ser excluído com segurança.
     

Na página de itens, ainda não aparece nenhum conteúdo porque você ainda não conectou nenhum dado à interface do usuário. Faça isso agora.

Carregando a ItemsPage

Quando a ItemsPage é carregada, você precisa obter a instância da fonte de dados do aplicativo e associá-la à interface do usuário. Para as páginas derivadas da LayoutAwarePage, você pode associar seus dados ao DefaultViewModel fornecido pela LayoutAwarePage. Isso é feito na substituição do método LoadState.

BR211380.wedge(pt-br,WIN.10).gifPara carregar os dados na página de itens

  1. Clique duas vezes em ItemPage.xaml.cs/vb no Gerenciador de Soluções para abri-lo.
  2. Adicione este código ao método LoadState.
    
                FeedDataSource feedDataSource = (FeedDataSource)App.Current.Resources["feedDataSource"];
    
                if (feedDataSource != null)
                {
                    this.DefaultViewModel["Items"] = feedDataSource.Feeds;
                }
    
    
  3. Pressione F5 para compilar e executar o aplicativo.

Agora, a ItemsPage é carregada e mostra uma grade de todos os blogs. Ele tem uma aparência semelhante a esta, mas os itens podem estar organizados de maneira diferente, dependendo da resolução da tela.

Página de Itens

Navegando para SplitPage

Quando o usuário seleciona um blog na coleção, você navega da página de itens para a página dividida. Para fazer essa navegação, os itens da GridView devem responder a um clique como um botão, em vez de serem selecionados. Para que seja possível clicar nos itens da GridView, defina as propriedades SelectionMode e IsItemClickEnabled conforme mostrado aqui. Em seguida, adicione um manipulador para o evento ItemClick da GridView.

BR211380.wedge(pt-br,WIN.10).gifPara navegar para SplitPage

  1. Clique duas vezes em ItemsPage.xaml no Gerenciador de Soluções para abri-lo.
  2. Encontre o controle GridView denominado itemGridView.
  3. No painel Propriedades, expanda a seção Comum e clique na seta para baixo na parte inferior da seção para expandir as propriedades avançadas.
  4. Marque a caixa para a propriedade IsItemClickEnabled. Isso define a propriedade como true.
  5. Adicione um manipulador para o evento ItemClick.
    1. No painel Propriedades, clique no botão Eventos (Botão Eventos).
    2. Localize o evento ItemClick na lista de eventos. Na caixa de texto do evento, digite "ItemView_ItemClick" como o nome do método que manipula o evento ItemClick.
    3. Pressione Enter. O método do manipulador de eventos será criado e aberto no editor de código para que você possa adicionar o código que será executado quando o evento ocorrer.
    4. Adicione esse código ao manipulador do evento ItemView_ItemClick no código atrás da página.

      Aqui, você navega para a página dividida e passa o título do feed selecionado.

      
                  // Navigate to the split page, configuring the new page
                  // by passing the title of the clicked item as a navigation parameter
      
                  if (e.ClickedItem != null)
                  {
                      string title = ((FeedData)e.ClickedItem).Title;
                      this.Frame.Navigate(typeof(SplitPage), title);
                  }
      
      
  6. Na ItemsPage.xaml, selecione o controle ListView denominado itemListView.
  7. Na janela Propriedades, clique no botão Propriedades (Botão Eventos).
  8. Repita as etapas 4 a 5.3 para o controle itemListView.

A lista itemListView é mostrada no lugar da grade quando o aplicativo é Ajustado. Falaremos mais sobre isso na seção Adaptando a diferentes layouts. Por enquanto, você só faz na ListView as mesmas alterações que fez na GridView para que elas tenham o mesmo comportamento.

Para navegar entre as páginas, você usa os métodos Navigate, GoForward e GoBack do controle Frame. Para retroceder a navegação, os modelos de página do Visual Studio incluem um botão Voltar. O manipulador do evento BackButton's Click chama o método Frame.GoBack.

O método Navigate(TypeName, Object) permite navegar e passar um objeto de dados para a nova página. Ele é usado para passar dados entre as páginas. O primeiro parâmetro, typeof(SplitPage), é o Type da página para a qual você está navegando. O segundo parâmetro é o objeto de dados que você passa para a página para a qual está navegando. Neste caso, é passado o título do item clicado.

Você poderia passar seus objetos de dados personalizados como parâmetros de navegação, mas eles não seriam persistentes e até causariam uma exceção ao salvar o estado da sessão do aplicativo usando a classe SuspensionManager. Para salvar o estado de navegação do aplicativo usando SuspensionManager, você deve passar apenas tipos básicos serializáveis como parâmetro de navegação. É por isso que você passa o título do item e tem um método na classe FeedDataSource para obter o item do título.

Antes de seguir para a página dividida, é preciso fazer mais uma alteração na página de itens. O título padrão da página é "Meu Aplicativo". Troque-o para "Blogs da Equipe do Windows".

BR211380.wedge(pt-br,WIN.10).gifPara alterar o título da página

  1. Clique duas vezes em ItemsPage.xaml no Gerenciador de Soluções para abri-lo.
  2. Selecione o TextBlock denominado pageTitle.
  3. Na janela Propriedades, clique no botão Propriedades (Botão Eventos).
  4. Em Comum no painel Propriedades, clique no marcador de propriedade referente à propriedade Text. O menu Propriedade é aberto.
    Observação   O marcador de propriedade é o símbolo de caixa pequena à direita de cada valor de propriedade. O marcador de propriedade Text é verde para indicar que está definido como um recurso.
     
  5. No menu Propriedade, selecione Editar Recurso.... A caixa de diálogo Editar Recurso é aberta.
  6. Na caixa de diálogo Editar Recurso, altere o valor de "Meu Aplicativo" para "Blogs da Equipe do Windows".
  7. Clique em OK.

Em ItemsPage.xaml, o título de página é associado a um recurso estático com a chave AppName. O texto nesse recurso é atualizado para "Blogs da Equipe do Windows" e o XAML agora se parece com este.


<x:String x:Key="AppName">Windows Team Blogs</x:String>

Pressione F5 para compilar e executar o aplicativo. Agora, quando você clica em um item, a página dividida é carregada. Mas essa página ainda está em branco porque você ainda não a conectou aos dados.

Carregando a SplitPage

Na página code-behind de SplitPage.xaml.cs/vb, você precisa fazer algo com o objeto que acabou de ser passado da página de itens. Para isso, substitua mais uma vez o método LoadState. Esse método já foi adicionado no código do modelo de página, então basta modificá-lo para associar os dados. O navigationParameter tem o objeto de dados que foi passado da página de itens. Converta isso de volta em uma string e passe-a como o parâmetro do método FeedDataSource.GetFeed. Adicione os dados de feed retornados ao DefaultViewModel com a chave Feed e adicione a propriedade FeedData.Items ao DefaultViewModel com a chave Items.

BR211380.wedge(pt-br,WIN.10).gifPara carregar os dados na página dividida

  1. Clique duas vezes em SplitPage.xaml.cs/vb no Gerenciador de Soluções para abri-lo no editor de código.
  2. Adicione este código à parte superior do método LoadState, após os comentários "TODO".
    Dica   Expanda a região "Gerenciamento do estado da página" para ver o método LoadState.
     
    
    
                // TODO: Assign a bindable group to this.DefaultViewModel["Group"]
                // TODO: Assign a collection of bindable items to this.DefaultViewModel["Items"]
                string feedTitle = (string)navigationParameter;
                FeedData feedData = FeedDataSource.GetFeed(feedTitle);
                if (feedData != null)
                {
                    this.DefaultViewModel["Feed"] = feedData;
                    this.DefaultViewModel["Items"] = feedData.Items;
                }
    
    

Eis o método LoadState atualizado.



        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
            // TODO: Assign a bindable group to this.DefaultViewModel["Group"]
            // TODO: Assign a collection of bindable items to this.DefaultViewModel["Items"]
            string feedTitle = (string)navigationParameter;
            FeedData feedData = FeedDataSource.GetFeed(feedTitle);
            if (feedData != null)
            {
                this.DefaultViewModel["Feed"] = feedData;
                this.DefaultViewModel["Items"] = feedData.Items;
            }

            if (pageState == null)
            {
                // When this is a new page, select the first item automatically unless logical page
                // navigation is being used (see the logical page navigation #region below.)
                if (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View != null)
                {
                    this.itemsViewSource.View.MoveCurrentToFirst();
                }
            }
            else
            {
                // Restore the previously saved state associated with this page
                if (pageState.ContainsKey("SelectedItem") && this.itemsViewSource.View != null)
                {
                    // TODO: Invoke this.itemsViewSource.View.MoveCurrentTo() with the selected
                    //       item as specified by the value of pageState["SelectedItem"]
                }
            }
        }

Pressione F5 para compilar e executar o aplicativo. Agora, quando você navegar até a página de divisão, os dados serão exibidos e será possível selecionar uma das opções na lista de postagens de blog. Mas, o título da página ainda está em branco. Você vai corrigir isso agora.

No modelo de página do Visual Studio, os comentários "TODO" indicam onde você adiciona seu objeto de dados ao DefaultViewModel com a chave Group.



            // TODO: Assign a bindable group to this.DefaultViewModel["Group"]
            ...
                this.DefaultViewModel["Feed"] = feedData;


Você pode considerar um feed de blog como um grupo de postagens de blog, mas a leitura do código fica mais fácil se a chave Feed for usada no lugar de Group. Só que, como você usou a chave Feed, é preciso alterar a associação no título da página para associar à propriedade Feed, em vez de Group. Você também faz o título ocupar duas colunas para que ele não seja cortado.

BR211380.wedge(pt-br,WIN.10).gifPara atualizar o título da página

  1. Clique duas vezes em SplitPage.xaml no Gerenciador de Soluções para abri-lo.
  2. Selecione o Grid denominado titlePanel.
  3. Em Layout no painel Propriedades, defina a propriedade ColumnSpan como "2" e pressione Enter.
    Observação   Na largura padrão do painel Propriedades, a propriedade ColumnSpan é mostrada como Colum....
     

    O XAML é atualizado como mostrado aqui.

    
    <!-- Back button and page title -->
    <Grid x:Name="titlePanel" Grid.ColumnSpan="2">
    
    
  4. Selecione o TextBlock denominado pageTitle.
  5. Em Comum no painel Propriedades, clique no marcador de propriedade referente à propriedade Text. O menu Propriedade é aberto.
    Observação   O marcador de propriedade Text é laranja para indicar que está definido como uma associação.
     
  6. No menu Propriedade, selecione Criar Vinculação de Dados.... A caixa de diálogo Criar Vinculação de Dados será aberta.
  7. Na caixa de diálogo Criar Vinculação de Dados, altere o valor na caixa de texto Caminho para "Feed.Title" e clique em OK.

    O XAML do TextBlock é atualizado desta forma.

    
    <TextBlock x:Name="pageTitle" Grid.Column="1" Text="{Binding Feed.Title}" 
               Style="{StaticResource PageHeaderTextStyle}"/>
    
    
  8. Pressione F5 para compilar e executar o aplicativo. Agora, quando você navegar até a página de divisão, o título da página será mostrado.

Página dividida com estilos padrão

Adicionar o WebView

Por padrão, o modelo de página dividida mostra os detalhes do item selecionado em um TextBlock. No entanto, a cadeia de caracteres que contém o conteúdo da postagem não é texto sem formatação, mas uma cadeia de HTML. Quando você mostra a cadeia de caracteres em um TextBlock, aparecem muitas marcas HTML, o que não é o desejado. Em vez disso, use um controle WebView para exibir o HTML. Você também altera o layout usado para mostrar o título e o conteúdo da postagem de blog selecionada.

BR211380.wedge(pt-br,WIN.10).gifPara adicionar o modo de exibição da Web

  1. Na SplitPage.xaml, exclua o ScrollViewer denominado itemDetail e todo o seu conteúdo.
  2. No editor de XAML, adicione este XAML no lugar do ScrollViewer itemDetail que você excluiu.
    
            <!-- Details for selected item -->
            <ScrollViewer
                x:Name="itemDetail"
                AutomationProperties.AutomationId="ItemDetailScrollViewer"
                Grid.Column="1"
                Grid.Row="1"
                Padding="70,0,120,0"
                DataContext="{Binding SelectedItem, ElementName=itemListView}"
                Style="{StaticResource VerticalScrollViewerStyle}">
            
                <Grid x:Name="itemDetailGrid">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
            
                    <TextBlock x:Name="itemTitle" Text="{Binding Title}" 
                               Style="{StaticResource SubheaderTextStyle}"/>
                    <Border x:Name="contentViewBorder" BorderBrush="Gray" BorderThickness="2" 
                            Grid.Row="1" Margin="0,15,0,20">
                        <Grid>
                            <WebView x:Name="contentView" />
                            <Rectangle x:Name="contentViewRect" />
                        </Grid>    
                    </Border>
                </Grid>
            </ScrollViewer>
    
    

O controle WebView oferece uma maneira de hospedar dados HTML no aplicativo. Mas, observando a propriedade Source, você vê que ele utiliza o Uri para exibição da página da Web. Os dados HTML são apenas uma cadeia de caracteres de HTML. Eles não possuem um Uri que você possa associar à propriedade Source. Felizmente, há um método NavigateToString para o qual a cadeia de caracteres de HTML pode ser passada.

Sempre que você usar um controle WebView para exibir o conteúdo que pode não estar disponível, lide com todas as falhas que ocorrerem.

Aqui, você manipula o evento NavigationCompleted para mostrar a mensagem de erro no controle WebView em caso de falha na navegação.

BR211380.wedge(pt-br,WIN.10).gifPara manipular erros de navegação

  1. Selecione o WebView denominado contentView que você adicionou na etapa anterior.
  2. Na janela Propriedades, clique no botão Eventos (Botão Eventos).
  3. Localize o evento NavigationCompleted na lista de eventos. Na caixa de texto do evento, digite "ContentView_NavigationCompleted" como o nome do método que manipula o evento NavigationCompleted.
  4. Pressione Enter. O método do manipulador de eventos será criado e aberto no editor de código para que você possa adicionar o código que será executado quando o evento ocorrer.
  5. Adicione este código ao manipulador de evento ContentView_NavigationCompleted na página code-behind.
    
        if (!e.IsSuccess)
        {
            string errorString = "<p>Page could not be loaded.</p><p>Error is: " + e.WebErrorStatus.ToString() + "</p>";
            this.contentView.NavigateToString(errorString);
        }
    
    

Para popular o WebView, você adiciona seu código ao manipulador de evento ItemListView_SelectionChanged. No manipulador de evento, você converte o item selecionado em um FeedItem e obtém a cadeia de caracteres de HTML com base na propriedade Content. Depois, passa a cadeia de caracteres para o método NavigateToString. Se nenhum item estiver selecionado, limpe o WebView passando uma cadeia de caracteres vazia.

BR211380.wedge(pt-br,WIN.10).gifPara popular o modo de exibição da Web

  1. Clique duas vezes no SplitPage.xaml.cs/vb, no Gerenciador de Soluções. O arquivo é aberto no editor de código.
  2. Adicione este código ao final do método ItemListView_SelectionChanged para popular o WebView com o conteúdo da postagem de blog selecionada.
    Observação   Expanda a região "Navegação de página lógica" para ver o método ItemListView_SelectionChanged.
     
    
    
                // Add this code to populate the web view
                //  with the content of the selected blog post.
                Selector list = sender as Selector;
                FeedItem selectedItem = list.SelectedItem as FeedItem;
                if (selectedItem != null)
                {
                    this.contentView.NavigateToString(selectedItem.Content);
                }
                else
                {
                    this.contentView.NavigateToString("");
                }      
    
    
    
  3. Pressione F5 para compilar e executar o aplicativo.

A página dividida tem melhor aparência agora e mostra a postagem do blog selecionada em um formato mais legível.

Página dividida com estilos padrão

Carregar a DetailPage

Agora, você adiciona conteúdo à página de detalhes. No DetailPage.xaml, é preciso associar o TextBlock de título ao título da postagem de blog e adicionar um controle WebView para mostrar a página do blog.

BR211380.wedge(pt-br,WIN.10).gifPara atualizar a página de detalhes

  1. Clique duas vezes em DetailPage.xaml no Gerenciador de Soluções para abri-lo.
  2. Associe o título da página TextBlock à propriedade Title da postagem de blog selecionada.
    1. Selecione o TextBlock denominado pageTitle.
    2. Na janela Propriedades, clique no botão Propriedades (Botão Eventos).
    3. Em Comum no painel Propriedades, clique no marcador de propriedade referente à propriedade Text. O menu Propriedade é aberto.
    4. No menu Propriedade, selecione Criar Vinculação de Dados.... A caixa de diálogo Criar Vinculação de Dados será aberta.
    5. Na caixa de diálogo Criar Associação de Dados, selecione Contexto de dados na lista suspensa Tipo de associação.
    6. Insira "Título" na caixa de texto Caminho e clique em OK.
      Observação  A mensagem na caixa de diálogo Criar Associação de Dados informa que o contexto de dados não está definido. Tudo bem, porque você define o contexto de dados no código quando executa o aplicativo.
       
  3. No editor de XAML, adicione este XAML após a Grid que contém o título da página e antes da seção VisualStateManager.VisualStateGroups.
    
    
            <Border x:Name="contentViewBorder" BorderBrush="Gray" BorderThickness="2" 
                    Grid.Row="1" Margin="120,15,20,20">
                <WebView x:Name="contentView" 
                         NavigationCompleted="contentView_NavigationCompleted"/>
            </Border>
    
    
  4. Clique duas vezes em DetailPage.xaml.cs/vb no Gerenciador de Soluções para abri-lo.
  5. Adicione este código à substituição do método LoadState.

    Este código navega o WebView para o URI (Uniform Resource Identifier) da postagem de blog e define o DataContext da página.

    
    
                // Add this code to navigate the web view to the selected blog post.
                string itemTitle = (string)navigationParameter;
                FeedItem feedItem = FeedDataSource.GetItem(itemTitle);
                if (feedItem != null)
                {
                    this.contentView.Navigate(feedItem.Link);
                    this.DataContext = feedItem;
                }
    
    
    
  6. Adicione este código à classe DetailPage para manipular o evento WebView.NavigationCompleted.
    
            private void contentView_NavigationCompleted(object sender, WebViewNavigationCompletedEventArgs e)
            {
                if (!e.IsSuccess)
                {
                    string errorString = "<p>Page could not be loaded.</p><p>Error is: " + e.WebErrorStatus.ToString() + "</p>";
                    this.contentView.NavigateToString(errorString);
                }
            }
    
    
    
  7. Pressione F5 para compilar e executar o aplicativo.

    Agora todos os dados estão associados, mas não há nenhuma maneira de navegar para a página de detalhes que você criou. Você adiciona a navegação para a página de detalhes a seguir.

Adicionando uma barra de aplicativos

A maior parte da navegação no aplicativo leitor de blog ocorre quando o usuário escolhe um item na interface do usuário. Porém, na página dividida, é preciso fornecer uma maneira para que o usuário vá para o modo de exibição de detalhe da postagem de blog. Você poderia colocar um botão em algum lugar na página, mas isso distrairia os usuários da função principal do aplicativo, que é a leitura. Em vez disso, coloque o botão em uma barra de aplicativos que ficará oculta até o usuário precisar dela.

Uma barra de aplicativos é uma parte da interface do usuário que é ocultada por padrão e é mostrada ou ignorada quando o usuário passa o dedo pela borda da tela ou interage com o aplicativo. Ela apresenta navegação, comandos e ferramentas para o usuário. Uma barra de aplicativos pode aparecer na parte superior e/ou inferior da página. Recomendamos colocar a navegação na parte superior da página e as ferramentas/comandos na parte inferior. Você pode controlar como e quando a barra de aplicativos é mostrada e ignorada, definindo as propriedades IsSticky e IsOpen. Você também pode responder à abertura e ao descarte da barra de ferramentas lidando com os eventos Opened e Closed.

Para adicionar uma barra de aplicativos no XAML, você atribui um controle AppBar à propriedade TopAppBar ou BottomAppBar de uma Page. Você adicionará uma barra de aplicativos superior com um botão para navegar até a página de detalhes. O arquivo StandardStyles.xaml contém diversos estilos de botão da barra de aplicativos para cenários comuns. Use esses estilos como guia para criar um estilo para seu botão. Coloque seu estilo na seção Page.Resources de SplitPage.xaml e adicione o XAML Page.TopAppBar logo após a seção de recursos.

BR211380.wedge(pt-br,WIN.10).gifPara adicionar uma barra de aplicativos

  1. Clique duas vezes em SplitPage.xaml no Gerenciador de Soluções para abri-lo.
  2. No editor de XAML, adicione este XAML à seção Page.Resources próxima ao topo da página.

    Isso adiciona o recurso Style para o botão da barra de aplicativos. Falaremos mais sobre os estilos posteriormente na seção Criando uma aparência consistente com estilos.

    
    
        <Style x:Key="WebViewAppBarButtonStyle" TargetType="Button" 
               BasedOn="{StaticResource AppBarButtonStyle}">
            <Setter Property="AutomationProperties.AutomationId" Value="WebViewAppBarButton"/>
            <Setter Property="AutomationProperties.Name" Value="View Web Page"/>
            <Setter Property="Content" Value="&#xE12B;"/>
        </Style>
    
    
    
  3. Adicione este XAML após a seção Page.Resources da página.

    Isso adiciona um controle AppBar à propriedade TopAppBar da página.

    
    <Page.TopAppBar>
       <AppBar Padding="10,0,10,0">
            <Grid>
    
                <Button HorizontalAlignment="Right" 
                        Style="{StaticResource WebViewAppBarButtonStyle}"/>
            </Grid>
        </AppBar>
    </Page.TopAppBar>
    
    
  4. Selecione o Button na barra de aplicativos que você acabou de adicionar.
  5. Na janela Propriedades, clique no botão Eventos (Botão Eventos).
  6. Localize o evento Click na parte superior da lista de eventos. Na caixa de texto do evento, digite "ViewDetail_Click" como o nome do método que manipula o evento Click.
  7. Pressione Enter. O método do manipulador de eventos será criado e aberto no editor de código para que você possa adicionar o código que será executado quando o evento ocorrer.
  8. Adicione este código ao método do manipulador de evento para manipular a navegação para a página de detalhes.
    
    
                FeedItem selectedItem = this.itemListView.SelectedItem as FeedItem;
                if (selectedItem != null && this.Frame != null)
                {
                    string itemTitle = selectedItem.Title;
                    this.Frame.Navigate(typeof(DetailPage), itemTitle);
                }
    
    
    
  9. Pressione F5 para compilar e executar o aplicativo. Clique em um blog para navegar até a página de divisão e selecione uma postagem de blog para leitura. Clique com o botão direito do mouse no cabeçalho da página para mostrar a barra do aplicativo e clique no botão Mostrar Exibição da Web para navegar até a página de detalhes.

Adicionando animações e transições

Quando falamos sobre animações, muitas vezes pensamos em objetos saltando pela tela. Porém, no XAML, uma animação é, essencialmente, apenas uma maneira de mudar o valor de uma propriedade em um objeto. Desse modo, as animações são úteis para muito mais do que apenas exibir bolas quicando. No aplicativo leitor de blog, você usa animações para adaptar sua interface do usuário a diferentes layouts e orientações. Isso será tratado em mais detalhes na próxima seção, mas, primeiro, você precisa entender como as animações funcionam.

Para usar uma animação, você a coloca dentro de um Storyboard. Quando o Storyboard é executado, a propriedade muda conforme especificado pela animação. Um Storyboard pode conter uma ou mais animações. Cada animação especifica um objeto de destino, uma propriedade a ser modificada nesse objeto e um novo valor para a propriedade.

Por exemplo, no aplicativo leitor de blog, você tem uma ListView chamada itemListView. Esta é uma animação que altera a propriedade Visibility da itemListView para Visible quando o Storyboard é executado.


<Storyboard>
    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" 
                                   Storyboard.TargetProperty="Visibility" >
        <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
    </ObjectAnimationUsingKeyFrames>
</Storyboard>


Adicionando animações de tema

Execute novamente o aplicativo e observe como os elementos da interface do usuário deslizam fluidamente quando uma página é carregada. Exceto para o controle WebView que você adicionou: ele simplesmente é exibido. O Windows 8 usa animações e transições para aperfeiçoar a experiência do usuário em toda a interface do usuário. Você quer ter a mesma experiência em seu aplicativo para combinar com a personalidade do Windows 8. Felizmente, é possível usar animações de tema e transições de tema internas no aplicativo para corresponder àquelas usadas no Windows 8. Elas estão no namespace Windows.UI.Xaml.Media.Animation.

Uma animação de tema é uma animação pré-configurada que pode ser incluída em um Storyboard. A PopInThemeAnimation faz a exibição da Web deslizar da direita para a esquerda quando a página é carregada. O aumento do valor da propriedade FromHorizontalOffset torna o efeito mais intenso. Aqui, você coloca a PopInThemeAnimation em um Storyboard e a torna um recurso no DetailPage.xaml. Defina o destino da animação como sendo a Border que envolve seu conteúdo da Web. Isso anima a Border e tudo o que está contido nela.

BR211380.wedge(pt-br,WIN.10).gifPara adicionar um recurso de tema

  1. Clique duas vezes em DetailPage.xaml no Gerenciador de Soluções para abri-lo.
  2. No editor de XAML, adicione este XAML à seção Page.Resources.
    
    
        <Storyboard x:Name="PopInStoryboard">
            <PopInThemeAnimation  Storyboard.TargetName="contentViewBorder" 
                                  FromHorizontalOffset="400"/>
        </Storyboard>
    
    
    

Na página code-behind, você inicia o Storyboard no método LoadState para que a animação pop-in seja aplicada à Border quando o usuário navegar para a página de detalhes.

BR211380.wedge(pt-br,WIN.10).gifPara iniciar um storyboard de animação

  1. Clique duas vezes em DetailPage.xaml.cs/vb no Gerenciador de Soluções para abri-lo.
  2. Adicione este código ao início do método LoadState.
    
    
                // Run the PopInThemeAnimation 
                Windows.UI.Xaml.Media.Animation.Storyboard sb =
                    this.FindName("PopInStoryboard") as Windows.UI.Xaml.Media.Animation.Storyboard;
                if (sb != null) sb.Begin();
    
    
    
  3. Pressione F5 para compilar e executar o aplicativo. Navegue para a página de detalhes. Agora, o controle WebView desliza junto com os outros elementos da interface do usuário quando a página de divisão é carregada.

Este é o código atualizado do método LoadState.


        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
            // Run the PopInThemeAnimation 
            Windows.UI.Xaml.Media.Animation.Storyboard sb =
                this.FindName("PopInStoryboard") as Windows.UI.Xaml.Media.Animation.Storyboard;
            if (sb != null) sb.Begin();

            // Add this code to navigate the web view to the selected blog post.
            string itemTitle = (string)navigationParameter;
            FeedItem feedItem = FeedDataSource.GetItem(itemTitle);
            if (feedItem != null)
            {
                this.contentView.Navigate(feedItem.Link);
                this.DataContext = feedItem;
            }
        }

Você também pode seguir estas etapas e usar o mesmo código para adicionar esta animação ao elemento contentViewBorder na SplitPage.

Para saber mais e obter uma lista completa de animações e transições de tema, veja o guia de início rápido sobre como animar sua interface do usuário usando as animações da biblioteca.

Criando uma aparência consistente com estilos

Você quer que o aplicativo leitor de blog tenha a mesma aparência que o site de blogs da equipe do Windows. Seu objetivo é que os usuários tenham uma experiência integrada ao se moverem entre o site e o aplicativo. O tema escuro padrão do projeto não combina muito com o site de blogs da equipe do Windows. Isso fica mais evidente na página de detalhes, onde você carrega a página real do blog em uma WebView, como mostrado aqui:

Página de detalhes com tema escuro.

Para que o aplicativo tenha uma aparência consistente que você possa atualizar quando necessário, são usados pincéis e estilos. Com um Brush, você pode definir uma aparência em um lugar e usá-la sempre que for preciso. Com um Style, você pode definir valores para as propriedades de um controle e reutilizar essas configurações por todo o aplicativo.

Antes de entrarmos em detalhes, vamos ver como usar um pincel para definir a cor da tela de fundo das páginas do aplicativo. Cada página do aplicativo tem uma Grid raiz com uma propriedade Background para definir a cor da tela de fundo da página. A tela de fundo de cada página poderia ser definida individualmente, assim:


<Grid Background="Blue">

Um jeito melhor é definir um Brush como um recurso e usá-lo para definir a cor da tela de fundo de todas as páginas. Você define objetos e valores como recursos para torná-los reutilizáveis. Para usar um objeto ou valor como um recurso, é preciso definir seu atributo x:Key. Use essa chave para fazer referência ao recurso no XAML. Aqui, a tela de fundo é definida como um recurso com a chave ApplicationPageBackgroundThemeBrush, que é um SolidColorBrush definido pelo sistema.


<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">

É possível definir a propriedade Background de Grid, mas, em geral, você precisa definir mais de uma propriedade para obter a aparência desejada. Você pode agrupar configurações para qualquer número de propriedades em conjunto em um Style e aplicar Style ao controle.

Você pode definir recursos no arquivo XAML de uma página individual, no arquivo App.xaml ou em um arquivo XAML de dicionário de recursos separado, como StandardStyles.xaml. O local onde o recurso é definido determina o escopo no qual ele pode ser usado. O Visual Studio cria o arquivo StandardStyles.xaml como parte do modelo de projeto e o coloca na pasta Common. É um dicionário de recursos que contém os valores, estilos e modelos de dados usados nos modelos de página do Visual Studio. Um arquivo XAML do dicionário de recursos pode ser compartilhado entre aplicativos e mais de um dicionário de recursos pode ser mesclado em um único aplicativo.

No aplicativo leitor de blog, você define recursos no App.xaml para torná-los disponíveis no aplicativo inteiro. Há também alguns recursos definidos no arquivo XAML para páginas individuais. Esses recursos só estão disponíveis na página em que estão definidos. Se recursos com a mesma chave forem definidos em App.xaml e em uma página, o recurso na página substituirá o recurso em App.xaml. Da mesma maneira, um recurso definido em App.xaml substituirá um recurso definido com a mesma chave em um arquivo de dicionário de recursos separado. Para saber mais, veja Guia de início rápido: definindo o estilo de controles.

Vamos ver agora um exemplo de como usar Styles no aplicativo. A aparência das páginas do modelo é definida por um estilo com a chave LayoutRootStyle. A definição de Style está contida no arquivo StandardStyles.xaml.


<Grid Style="{StaticResource LayoutRootStyle}">



    <!-- Page layout roots typically use entrance animations  
         and a theme-appropriate background color -->

    <Style x:Key="LayoutRootStyle" TargetType="Panel">
        <Setter Property="Background" 
                Value="{StaticResource ApplicationPageBackgroundThemeBrush}"/>
        <Setter Property="ChildrenTransitions">
            <Setter.Value>
                <TransitionCollection>
                    <EntranceThemeTransition/>
                </TransitionCollection>
            </Setter.Value>
        </Setter>
    </Style>

Na definição de Style, você precisa de um atributo TargetType e de uma coleção de um ou mais Setters. Você define o TargetType como uma cadeia de caracteres que especifica o tipo ao qual o Style é aplicado, neste caso, Panel. Se você tentar aplicar um Style a um controle que não corresponda ao atributo TargetType, ocorrerá uma exceção. Cada elemento Setter requer uma Property e um Value. Essas configurações de propriedade indicam a qual propriedade de controle a configuração se aplica, e qual é o valor a ser definido para essa propriedade.

Para mudar o Background das suas páginas, você precisa substituir o ApplicationPageBackgroundThemeBrush pelo seu próprio pincel personalizado. Para esse pincel personalizado, use a Color #FF0A2562, um azul agradável que combina com as cores do site http://windowsteamblog.com. Para substituir o pincel de tema do sistema, crie um novo Style baseado em LayoutRootStyle e altere a propriedade Background nesse local. Aqui você define um novo estilo para a raiz do layout.

BR211380.wedge(pt-br,WIN.10).gifPara alterar o plano de fundo da página

  1. Clique duas vezes em App.xaml no Gerenciador de Soluções para abri-lo.
  2. No editor de XAML, adicione estas definições de pincel e estilo ao ResourceDictionary junto com seus outros recursos específicos ao aplicativo, após o recurso feedDataSource.
    
    
                <SolidColorBrush x:Key="WindowsBlogBackgroundBrush" 
                                        Color="#FF0A2562"/>
                <Style x:Key="WindowsBlogLayoutRootStyle" 
                               TargetType="Panel" 
                               BasedOn="{StaticResource LayoutRootStyle}">
                    <Setter Property="Background" 
                                    Value="{StaticResource WindowsBlogBackgroundBrush}"/>
                </Style>
    
    

Este é o XAML completo para a seção ResourceDictionary de App.xaml.


    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- 
                    Styles that define common aspects of the platform look and feel
                    Required by Visual Studio project and item templates
                 -->
                <ResourceDictionary Source="Common/StandardStyles.xaml"/>
            </ResourceDictionary.MergedDictionaries>

            <local:FeedDataSource x:Key="feedDataSource"/>

            <SolidColorBrush x:Key="WindowsBlogBackgroundBrush" 
                                    Color="#FF0A2562"/>
            <Style x:Key="WindowsBlogLayoutRootStyle" 
                           TargetType="Panel" 
                           BasedOn="{StaticResource LayoutRootStyle}">
                <Setter Property="Background" 
                                Value="{StaticResource WindowsBlogBackgroundBrush}"/>
            </Style>
        </ResourceDictionary>
    </Application.Resources>

Importante   Como você baseou um estilo em um estilo do sistema no StandardStyles.xaml, o ResourceDictionary que inclui o StandardStyles.xaml tem que ser declarado no XAML antes do estilo que se baseia nele. Se isso não for feito, o analisador XAML não conseguirá encontrar o LayoutRootStyle no qual seu estilo se baseia.
 

A linha BasedOn="{StaticResource LayoutRootStyle}" indica que o novo Style deve herdar do LayoutRootStyle todas as propriedades que você não definir explicitamente. O novo Style é exatamente igual ao estilo padrão, só que com uma tela de fundo azul, e você pode usá-lo para todas as suas páginas.

BR211380.wedge(pt-br,WIN.10).gifPara alterar o plano de fundo de cada página

  1. Clique duas vezes em ItemsPage.xaml no Gerenciador de Soluções para abri-lo.
  2. Selecione a Grid do layout raiz da página.
  3. Em Diversos no painel Propriedades, encontre a propriedade Style.
  4. Clique no marcador de propriedade ao lado da propriedade Style para abrir o menu.
  5. No menu, selecione Recurso local > WindowsBlogLayoutRootStyle.
  6. Repita as etapas 2 a 5 do SplitPage.xaml e do DetailPage.xaml.

    O XAML da Grid raiz em cada página, agora, tem esta aparência.

    
    
     <Grid Style="{StaticResource WindowsBlogLayoutRootStyle}">
    
    
  7. Pressione F5 para compilar e executar o aplicativo e veja agora as páginas azuis.

Para dar ao aplicativo o visual do site de blogs da equipe do Windows, você também usa modelos de dados personalizados além de instâncias de Brush e Style. Vamos começar usando modelos para formatar os itens de lista na página dividida.

Formatando dados com um modelo de dados

No SplitPage.xaml, a aparência dos itens na itemListView é definida no Standard130ItemTemplate, que se encontra no StandardStyles.xaml. O modelo de item é atribuído nesta linha do XAML: ItemTemplate="{StaticResource Standard130ItemTemplate}". Para observar o efeito desse modelo, você pode removê-lo e ver como fica a lista sem ele.

Uma lista associada mostrando o título.

Você tem a ListView associada à propriedade Items do objeto FeedData; portanto, os dados corretos estão lá. Mas, quando o aplicativo é executado desta forma, a ListView não sabe o que mostrar, então ela só chama ToString no objeto ao qual está associada. Isso gera uma lista de cadeias de caracteres "WindowsBlogReader.FeedItem", como você viu antes. Obviamente, isso não é o que você quer mostrar.

Para deixar um pouco melhor, configure a propriedade DisplayMemberPath na ListView. Isso informa à exibição de lista para chamar ToString na propriedade especificada do objeto associado, e não no objeto em si. Se você configura DisplayMemberPath=Title, a ListView mostra uma lista de títulos de postagens de blog.

Este é o XAML da ListView com o DisplayMemberPath definido como a propriedade Title.


<ListView
    x:Name="itemListView"
    AutomationProperties.AutomationId="ItemsListView"
    AutomationProperties.Name="Items"
    TabIndex="1"
    Grid.Row="1"
    Margin="-10,-10,0,0"
    Padding="120,0,0,60"
    ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
    IsSwipeEnabled="False"
    SelectionChanged="ItemListView_SelectionChanged"
    DisplayMemberPath="Title"/>

Quando você executa o aplicativo, os itens de lista ficam com a aparência mostrada a seguir. Esse resultado está mais próximo daquilo que você quer mostrar.

Uma lista associada mostrando o título.

Mas o que você realmente quer é mostrar o título, o autor e a data de publicação de cada postagem na lista. Para mostrar mais de uma propriedade do item de dados, você define um modelo que informa à ListView exatamente como os dados devem ser exibidos. Os controles para exibir coleções de itens de dados são derivados da classe ItemsControl. Esses controles possuem uma propriedade ItemTemplate à qual se pode atribuir um DataTemplate. O DataTemplate define a aparência dos dados.

Importante   Não é possível usar o DisplayMemberPath e um ItemTemplate ao mesmo tempo. Ao definir a propriedade ItemTemplate, certifique-se de remover a configuração DisplayMemberPath.
 

O modelo de item padrão está próximo daquilo que você quer mostrar. Vamos usá-lo como ponto de partida do seu modelo.

BR211380.wedge(pt-br,WIN.10).gifPara criar um novo ItemTemplate

  1. No Gerenciador de Soluções, abra o SplitPage.xaml.
  2. Selecione a ListView denominada "itemListView".
  3. Na seção Diversos do painel Propriedades, clique no marcador de propriedade correspondente à propriedade ItemTemplate. O menu Propriedade é aberto.
    Observação   O marcador de propriedade é o símbolo de caixa pequena à direita de cada valor de propriedade. O marcador de propriedade ItemTemplate é verde para indicar que está definido como um recurso.
     
  4. No menu Propriedade, selecione Converter para novo recurso.... A caixa de diálogo Criar Recurso de DataTemplate é aberta.
  5. Na caixa de diálogo Criar Recurso de DataTemplate, digite "DefaultListItemTemplate" na caixa de texto Nome (chave).

    Verifique se a configuração Definir em está especificada como Este documento > "LayoutAwarePage:pageRoot".

    Observação   O modo de exibição Design da página XAML deve estar aparecendo no Visual Studio. Se apenas o editor de XAML estiver aparecendo, algumas opções estarão desabilitadas.
     
  6. Clique em OK.

    Um novo DataTemplate é criado na seção Resources do SplitPage.xaml. Essa é uma cópia do recurso Standard130ItemTemplate que você pode modificar. A propriedade ItemTemplate de itemListView também é atualizada para usar DefaultListItemTemplate.

Definir a parte da interface do usuário dentro do DataTemplate é como definir qualquer outra interface do usuário. Esse modelo apresenta uma Grid com duas colunas. A primeira coluna tem uma borda quadrada com uma imagem de espaço reservado. A segunda coluna tem um StackPanel com três TextBlocks empilhados uns sobre os outros. Por padrão, as propriedades Text dos TextBlocks estão associadas a propriedades da fonte de dados de exemplo utilizada nos modelos do Visual Studio. O DataContext padrão para essas associações é o objeto exibido na ListView, que é um FeedItem. Assim, você pode atualizar as associações para mostrar as propriedades Title, Author e PubDate do FeedItem.

Este é o XAML do modelo de dados com as associações atualizadas.


        <DataTemplate x:Key="DefaultListItemTemplate">
            <Grid Height="110" Margin="6">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" 
                        Width="110" Height="110">
                    <Image Source="{Binding Image}" Stretch="UniformToFill" 
                           AutomationProperties.Name="{Binding Title}"/>
                </Border>
                <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
                    <TextBlock Text="{Binding Title}" 
                               Style="{StaticResource TitleTextStyle}" TextWrapping="NoWrap"/>
                    <TextBlock Text="{Binding Author}" 
																															Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
                    <TextBlock Text="{Binding PubDate}" 
																															Style="{StaticResource BodyTextStyle}" MaxHeight="60"/>
                </StackPanel>
            </Grid>
        </DataTemplate>

A lista fica com a aparência a seguir quando você executa o aplicativo.

Uma lista associada usando um modelo de dados.

Agora a lista mostra os dados desejados, mas não reflete a identidade visual do site de blogs da equipe do Windows, como se vê aqui.

Listagem de postagens de blogs do Windows.

Para que a exibição de lista fique mais parecida com o site, você usa um ContentControl e um ControlTemplate para mostrar a data em um bloco verde e atualiza o visual do TextBlock de título para mostrar os títulos em laranja. Você também usa um conversor de valor para formatar a data do jeito que deseja.

Formatando dados com um conversor de valor

No DataTemplate da ItemListView, você associa a propriedade PubDate, que é uma DateTime, a uma propriedade TextBlock.Text. O mecanismo de associação converte automaticamente PubDate de uma DateTime em uma cadeia de caracteres. Mas a conversão automática mostra a data e a hora, e você só quer mostrar a data. Para corrigir isso, você pode criar seu próprio conversor de valor que converta uma DateTime em uma cadeia de caracteres, e nele formatar a cadeia de caracteres como quiser.

Para criar um conversor de valor, crie uma classe que implementa a interface IValueConverter e depois implemente os métodos Convert e ConvertBack. Os conversores podem mudar dados de um tipo para outro, converter dados com base em informações culturais ou modificar outros aspectos da apresentação.

Os métodos Convert e ConvertBack também permitem que você informe um parâmetro para que possa usar a mesma instância do conversor com opções diferentes. Neste exemplo, há um conversor de formatação que produz diferentes formatos da data com base no parâmetro de entrada. Você pode usar o ConverterParameter da classe Binding para passar um parâmetro como um argumento nos métodos Convert e ConvertBack. Use esse recurso para formatar a data de maneira a exibi-la no formato de bloco usado no site de blogs.

Aqui você cria um conversor de data que converte o valor de data que foi passado e o formata para que mostre apenas o dia, o mês e o ano.

BR211380.wedge(pt-br,WIN.10).gifPara adicionar um conversor de valor

  1. Selecione Projeto > Adicionar Classe. A caixa de diálogo Novo Item é aberta.
  2. Digite DateConverter como o nome para o arquivo de classe.
  3. Clique em Adicionar. O arquivo de classe DateConverter.cs/vb será criado.
  4. Copie este código para o arquivo DateConverter.cs/vb. Substitua qualquer código que esteja no arquivo.
    
    
    using System;
    using Windows.Globalization.DateTimeFormatting;
    
    namespace WindowsBlogReader
    {
        public class DateConverter : Windows.UI.Xaml.Data.IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string culture)
            {
                if (value == null)
                    throw new ArgumentNullException("value", "Value cannot be null.");
    
                if (!typeof(DateTime).Equals(value.GetType()))
                    throw new ArgumentException("Value must be of type DateTime.", "value");
                
                DateTime dt = (DateTime)value;
    
                if (parameter == null)
                {
                    // Date "7/27/2011 9:30:59 AM" returns "7/27/2011"
                    return DateTimeFormatter.ShortDate.Format(dt);
                }           
                else if ((string)parameter == "day")
                {
                    // Date "7/27/2011 9:30:59 AM" returns "27"
                    DateTimeFormatter dateFormatter = new DateTimeFormatter("{day.integer(2)}");
                    return dateFormatter.Format(dt);
                }
                else if ((string)parameter == "month")
                {
                    // Date "7/27/2011 9:30:59 AM" returns "JUL"
                    DateTimeFormatter dateFormatter = new DateTimeFormatter("{month.abbreviated(3)}");
                    return dateFormatter.Format(dt).ToUpper();
                }
                else if ((string)parameter == "year")
                {
                    // Date "7/27/2011 9:30:59 AM" returns "2011"
                    DateTimeFormatter dateFormatter = new DateTimeFormatter("{year.full}");
                    return dateFormatter.Format(dt);
                }
                else
                {
                    // Requested format is unknown. Return in the original format.
                    return dt.ToString();
                }
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string culture)
            {
                string strValue = value as string;
                DateTime resultDateTime;
                if (DateTime.TryParse(strValue, out resultDateTime))
                {
                    return resultDateTime;
                }
                return Windows.UI.Xaml.DependencyProperty.UnsetValue;
            }
        }
    }
    
    
    
  5. Clique em Compilar > Compilar solução para garantir que a solução seja compilada sem erros.

Para poder usar a classe DateConverter, você deve declarar uma instância dela no seu XAML como um recurso de aplicativo com a chave dateConverter no App.xaml. Declarando-a aqui, ela fica disponível para uso em cada página do aplicativo.

BR211380.wedge(pt-br,WIN.10).gifPara adicionar o recurso de aplicativo dateConverter

  1. Clique duas vezes em App.xaml no Gerenciador de Soluções para abri-lo.
  2. Adicione a declaração de recurso, <local:DateConverter x:Key="dateConverter" />, ao ResourceDictionary após o recurso feedDataSource.

Agora você pode usar o DateConverter nas associações do bloco de data que criar em seguida. Com o conversor adicionado, o mecanismo de associação usa o DateConverter personalizado para transformar uma DateTime em uma cadeia de caracteres. A cadeia de caracteres resultante é formatada da maneira desejada, contendo apenas dia, mês e ano.

No App.xaml, você adiciona um ControlTemplate que define um bloco quadrado mostrando a data. Defina isso no App.xaml para poder usá-lo no ItemsPage.xaml e no SplitPage.xaml.

BR211380.wedge(pt-br,WIN.10).gif Para adicionar um modelo de controle ao App.xaml

  1. Clique duas vezes em App.xaml no Gerenciador de Soluções para abri-lo.
  2. Adicione o XAML do ResourceDictionary aos demais recursos específicos do aplicativo, após o recurso WindowsBlogLayoutRootStyle .
    
    
    <ControlTemplate x:Key="DateBlockTemplate">
        <Canvas Height="86" Width="86"  Margin="8,8,0,8" HorizontalAlignment="Left" VerticalAlignment="Top">
            <TextBlock TextTrimming="WordEllipsis" TextWrapping="NoWrap" 
                       Width="Auto" Height="Auto" Margin="8,0,4,0" 
                       FontSize="32" FontWeight="Bold">
                <TextBlock.Text>
                    <Binding Path="PubDate" Converter="{StaticResource dateConverter}" ConverterParameter="month"  />
                </TextBlock.Text>
            </TextBlock>
    
            <TextBlock TextTrimming="WordEllipsis" TextWrapping="Wrap" 
                       Width="40" Height="Auto" Margin="8,0,0,0" 
                       FontSize="34" FontWeight="Bold" Canvas.Top="36">
                <TextBlock.Text>
                    <Binding Path="PubDate" Converter="{StaticResource dateConverter}" ConverterParameter="day"  />
                </TextBlock.Text>
            </TextBlock>
            <Line Stroke="White" StrokeThickness="2" X1="54" Y1="46" X2="54" Y2="80" />
    
            <TextBlock TextWrapping="Wrap" 
                Width="20" Height="Auto" 
                FontSize="{StaticResource ControlContentThemeFontSize}" Canvas.Top="42" Canvas.Left="60">
                <TextBlock.Text>
                    <Binding Path="PubDate" Converter="{StaticResource dateConverter}" ConverterParameter="year"  />
                </TextBlock.Text>
            </TextBlock>
        </Canvas>
    </ControlTemplate>
    
    

Agora você pode usar esse modelo de controle no SplitPage.xaml para atualizar a aparência dos itens de lista na exibição padrão.

BR211380.wedge(pt-br,WIN.10).gif Para usar o modelo de controle no SplitPage.xaml

  1. Clique duas vezes em SplitPage.xaml no Gerenciador de Soluções para abri-lo.
  2. No editor de XAML, localize o recurso DefaultListItemTemplate criado anteriormente.
  3. Substitua o XAML do elemento Border por este XAML.
    
                    <Border Background="#FF6BBD46" Width="110" Height="110">
                        <ContentControl Template="{StaticResource DateBlockTemplate}" />
                    </Border>
    
    
  4. Substitua o XAML pelos 3 TextBlocks do elemento StackPanel por este XAML.
    
                        <TextBlock Text="{Binding Title}" FontSize="26.667" TextWrapping="Wrap"
                                   MaxHeight="72" Foreground="#FFFE5815" />
                        <TextBlock Text="{Binding Author}" FontSize="18.667" />
    
    

Este é o XAML atualizado do modelo de dados.



        <DataTemplate x:Key="DefaultListItemTemplate">
            <Grid Height="110" Margin="6">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Border Background="#FF6BBD46" Width="110" Height="110">
                    <ContentControl Template="{StaticResource DateBlockTemplate}" />
                </Border>
                <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
                    <TextBlock Text="{Binding Title}" FontSize="26.667" TextWrapping="Wrap"
                               MaxHeight="72" Foreground="#FFFE5815" />
                    <TextBlock Text="{Binding Author}" FontSize="18.667" />
                </StackPanel>
            </Grid>
        </DataTemplate>

Importante   Esse modelo é usado no modo de exibição padrão de tela inteira com orientação paisagem. Se a resolução de tela tiver menos de 1.366 pixels de largura, a página dividida usará o estado da exibição FilledOrNarrow e esse modelo não aparecerá na exibição de lista. Para ver o modelo, execute o aplicativo no simulador do Visual Studio com resolução 1.366 x 768 ou superior. Para saber mais sobre como testar o aplicativo no simulador, veja o tópico sobre como Executar aplicativos da Windows Store no Visual Studio .
 

Para concluir a definição do estilo da página dividida, é preciso alterar a cor da tela de fundo da barra de aplicativos e a cor do item selecionado na exibição de lista.

BR211380.wedge(pt-br,WIN.10).gifPara atualizar o segundo plano da barra de aplicativos

  1. Na SplitPage.xaml, selecione o controle AppBar.
  2. Em Pincel no painel Propriedades, ou no editor XAML, defina a propriedade Background como "#F20A2562".
    
    <AppBar Padding="10,0,10,0" Background="#F20A2562">
    
    

Por padrão, o item selecionado na exibição de lista tem fundo roxo. Você substitui os pincéis de tema da exibição de lista padrão para deixar o item selecionado azul. Para substituir os pincéis de tema internos, defina um pincel com a mesma chave no App.xaml e dê a ele um novo valor.

BR211380.wedge(pt-br,WIN.10).gifPara atualizar as cores da exibição de lista

  1. Clique duas vezes em App.xaml no Gerenciador de Soluções para abri-lo.
  2. Adicione o XAML do ResourceDictionary após os demais recursos específicos do aplicativo.
    
    
    <SolidColorBrush x:Key="ListViewItemSelectedBackgroundThemeBrush" Color="#FF465985"/>
    <SolidColorBrush x:Key="ListViewItemSelectedPointerOverBackgroundThemeBrush" Color="#FF384A72"/>
    <SolidColorBrush x:Key="ListViewItemSelectedPointerOverBorderThemeBrush" Color="#FF384A72" />
    
    

Para concluir a definição do estilo do aplicativo, você aplica estilos semelhantes à página de itens. No ItemsPage.xaml, você adiciona esses recursos para definir a aparência dos itens de grade no modo de exibição padrão.

BR211380.wedge(pt-br,WIN.10).gif Para definir o estilo do ItemsPage.xaml

  1. Clique duas vezes em ItemsPage.xaml no Gerenciador de Soluções para abri-lo.
  2. No editor XAML, adicione este XAML da seção Page.Resources após o recurso AppName .
    
    
            <!-- light blue -->
            <SolidColorBrush x:Key="BlockBackgroundBrush" Color="#FF557EB9"/>
    
            <!-- Grid Styles -->
            <Style x:Key="GridTitleTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BasicTextStyle}">
                <Setter Property="FontSize" Value="26.667"/>
                <Setter Property="Margin" Value="12,0,12,2"/>
            </Style>
    
            <Style x:Key="GridDescriptionTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BasicTextStyle}">
                <Setter Property="VerticalAlignment" Value="Bottom"/>
                <Setter Property="Margin" Value="12,0,12,60"/>
            </Style>
    
            <DataTemplate x:Key="DefaultGridItemTemplate">
                <Grid HorizontalAlignment="Left" Width="250" Height="250">
                    <Border Background="{StaticResource BlockBackgroundBrush}" />
                    <TextBlock Text="{Binding Title}" Style="{StaticResource GridTitleTextStyle}"/>
                    <TextBlock Text="{Binding Description}" Style="{StaticResource GridDescriptionTextStyle}" />
                    <StackPanel VerticalAlignment="Bottom" Orientation="Horizontal"
                            Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
                        <TextBlock Text="Last Updated" Margin="12,4,0,8" Height="42"/>
                        <TextBlock Text="{Binding PubDate, Converter={StaticResource dateConverter}}" Margin="12,4,12,8" />
                    </StackPanel>
                </Grid>
            </DataTemplate>
    
    
  3. Encontre o controle GridView denominado itemGridView.
  4. Na seção Diversos do painel Propriedades, clique no marcador de propriedade correspondente à propriedade ItemTemplate. O menu Propriedade é aberto.
  5. No menu, selecione Recurso Local > DefaultGridItemTemplate.
    Observação   O modo de exibição Design da página XAML deve estar aparecendo no Visual Studio. Se apenas o editor de XAML estiver aparecendo, os recursos da página local não estarão listados.
     

    Este é o XAML completo atualizado para itemGridView.

    
    
            <!-- Horizontal scrolling grid used in most view states -->
            <GridView
                x:Name="itemGridView"
                AutomationProperties.AutomationId="ItemsGridView"
                AutomationProperties.Name="Items"
                TabIndex="1"
                Grid.RowSpan="2"
                Padding="116,136,116,46"
                ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
                
                ItemTemplate="{StaticResource DefaultGridItemTemplate}"
                
                SelectionMode="None"
                IsSwipeEnabled="false" 
                IsItemClickEnabled="True" 
                ItemClick="ItemView_ItemClick"/>
    
    
  6. Pressione F5 para compilar e executar o aplicativo. Agora a página de itens usa o novo modelo.

Com os estilos aplicados, o aplicativo corresponde à aparência do site de blogs da equipe do Windows:

Página de coleção de estilos.

Página dividida com o estilo.

Página de detalhes com o estilo.

Usando estilos e baseando-os em outros estilos, você pode rapidamente definir e aplicar visuais diferentes ao seu aplicativo. Na próxima seção, você combina o que sabe sobre animações e estilos para fazer com que o aplicativo se adapte facilmente a diversos layouts e orientações ao ser executado.

Adaptando a diferentes layouts

Observação   Nesta seção, você aplica os conceitos abordados na Parte 3: Navegação, layout e modos de exibição. Para saber mais sobre a adaptação de sua interface do usuário a diferentes modos de exibição e o suporte a ferramentas que está disponível, reveja a Parte 3.
 

Geralmente, um aplicativo é projetado para ser exibido em tela inteira na orientação paisagem. Porém, um aplicativo da Windows Store deve se adaptar a diferentes orientações e layouts. Especificamente, deve dar suporte às orientações paisagem e retrato. Na orientação paisagem, deve haver suporte para os layouts de Tela Inteira, Preenchido e Ajustado.

Dica   Para testar o aplicativo em diferentes orientações e resoluções, você pode executá-lo no simulador. Para executar seu aplicativo da Windows Store no simulador, selecione Simulador na lista suspensa ao lado do botão Iniciar Depuração, na barra de ferramentas Padrão. Para saber mais sobre o simulador, veja o tópico sobre como Executar aplicativos da Windows Store no Visual Studio .
 

Os modelos do Visual Studio incluem um código que trata de mudanças no estado da exibição. Esse código se encontra no arquivo LayoutAwarePage.cs/vb e mapeia o estado do aplicativo para estados visuais definidos no seu XAML. Como a lógica do layout da página já é fornecida para você, só é preciso fornecer os modos de exibição a serem usados para cada um dos estados visuais da página.

Para fazer a transição entre diferentes modos de exibição usando XAML, você usa o VisualStateManager para definir diversos VisualStates para seu aplicativo. Aqui você tem um VisualStateGroup definido no ItemsPage.xaml. Esse grupo tem quatro elementos de VisualState chamados de FullScreenLandscape, Filled, FullScreenPortrait e Snapped. Diferentes VisualStates do mesmo VisualStateGroup não podem ser usados ao mesmo tempo. Cada VisualState tem animações que indicam ao aplicativo o que precisa mudar da linha de base especificada no XAML para a interface do usuário.


<!--App Orientation States-->
  <VisualStateManager.VisualStateGroups>
     <VisualStateGroup x:Name="ApplicationViewStates">
        <VisualState x:Name="FullScreenLandscape" />
        <VisualState x:Name="Filled"> ... </VisualState>
        <VisualState x:Name="FullScreenPortrait"> ... </VisualState>
        <VisualState x:Name="Snapped"> ... </VisualState>
    </VisualStateGroup>
 </VisualStateManager.VisualStateGroups>

Você usa o estado FullScreenLandscape quando o aplicativo está em tela inteira na orientação paisagem. Como você criou o design da interface do usuário padrão para esse modo de exibição, não são necessárias mudanças e esse é apenas um VisualState vazio.

Você usa o estado Filled quando o usuário tem outro aplicativo ajustado em um lado da tela. A página de exibição de itens apenas se move nesse caso, e nenhuma mudança é necessária. Esse também é apenas um VisualState vazio.

Você usa o estado FullScreenPortrait quando o aplicativo é girado da orientação paisagem para retrato. Nesse estado visual, você tem duas animações. Uma muda o estilo usado para o botão Voltar, e a outra muda a margem da itemGridView, para que tudo se encaixe melhor na tela.


<!-- The entire page respects the narrower 100-pixel margin convention for portrait -->
<VisualState x:Name="FullScreenPortrait">
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" 
                                       Storyboard.TargetProperty="Style">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}"/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView" 
                                       Storyboard.TargetProperty="Padding">
            <DiscreteObjectKeyFrame KeyTime="0" Value="96,136,86,56"/>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualState>


Você usa o estado Snapped quando o usuário tem dois aplicativos sendo mostrados, e o seu aplicativo é o mais estreito dos dois. Neste estado, seu aplicativo tem apenas 320 DIPs de largura, por isso, é necessário fazer mudanças mais drásticas no layout. No XAML da interface do usuário da página de itens, um GridView e um ListView são definidos e associados à coleção de dados. Por padrão, o itemGridView é mostrado e o itemListView é recolhido. No estado Snapped, você tem quatro animações que recolhem itemGridView, mostram itemListView e mudam o Style do botão Voltar e do título da página para deixá-los menores.


<!--
    The back button and title have different styles when snapped, and the list representation is substituted
    for the grid displayed in all other view states
-->
<VisualState x:Name="Snapped">
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" 
                                       Storyboard.TargetProperty="Style">
            <DiscreteObjectKeyFrame KeyTime="0" 
                                    Value="{StaticResource SnappedBackButtonStyle}"/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" 
                                       Storyboard.TargetProperty="Style">
            <DiscreteObjectKeyFrame KeyTime="0" 
                                    Value="{StaticResource SnappedPageHeaderTextStyle}"/>
        </ObjectAnimationUsingKeyFrames>

        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" 
                                       Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView"
                                       Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualState>

Na seção Criando uma aparência consistente com estilos deste tutorial, você criou estilos e modelos para dar ao aplicativo uma aparência personalizada. A exibição de paisagem padrão usa esses estilos e modelos. Para manter a aparência personalizada em diferentes exibições, você também precisa criar estilos e modelos personalizados para essas exibições.

No ItemsPage.xaml, você criou um novo modelo de dados para os itens de grade. Também é preciso fornecer um novo modelo de dados para os itens de lista que aparecem no modo de exibição Snapped. Chame esse modelo de NarrowListItemTemplate e adicione-o à seção de recursos do ItemsPage.xaml, logo após o recurso DefaultGridItemTemplate.

BR211380.wedge(pt-br,WIN.10).gifPara adicionar um modelo ao modo de exibição ajustado

  1. Clique duas vezes em ItemsPage.xaml no Gerenciador de Soluções para abri-lo.
  2. No editor XAML, adicione este XAML da seção Page.Resources após o recurso DefaultGridItemTemplate .
    
            <!-- Used in Snapped view -->
            <DataTemplate x:Key="NarrowListItemTemplate">
                <Grid Height="80">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Border Background="{StaticResource BlockBackgroundBrush}" Width="80" Height="80" />
                    <ContentControl Template="{StaticResource DateBlockTemplate}" Margin="-12,-12,0,0"/>
                    <StackPanel Grid.Column="1" HorizontalAlignment="Left" Margin="12,8,0,0">
                        <TextBlock Text="{Binding Title}" MaxHeight="56" TextWrapping="Wrap"/>
                    </StackPanel>
                </Grid>
            </DataTemplate>
    
    
  3. Selecione o controle ListView denominado itemListView.
  4. Na seção Diversos do painel Propriedades, clique no marcador de propriedade correspondente à propriedade ItemTemplate. O menu Propriedade é aberto.
  5. No menu, selecione Recurso Local > NarrowListItemTemplate.

    Este é o XAML totalmente atualizado para itemListView.

    
    
            <!-- Vertical scrolling list only used when snapped -->
            <ListView
                x:Name="itemListView"
                AutomationProperties.AutomationId="ItemsListView"
                AutomationProperties.Name="Items"
                TabIndex="1"
                Grid.Row="1"
                Visibility="Collapsed"
                Margin="0,-10,0,0"
                Padding="10,0,0,60"
                ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
                ItemTemplate="{StaticResource NarrowListItemTemplate}"
                SelectionMode="None"
                IsSwipeEnabled="false" 
                IsItemClickEnabled="True" 
                ItemClick="ItemView_ItemClick"/>
    
    

Em ItemsPage, você tem um GridView e um ListView, e aplica os modelos no XAML padrão. Você mostra o GridView do modo de exibição padrão. Quando o aplicativo é ajustado, você substitui a grade pelo ListView usando o VisualStateManager para alterar as propriedades de Visibility dos dois modos de exibição.

Em SplitPage, é usada uma maneira diferente de alterar a interface do usuário quando o modo de exibição muda. Você tem um único ListView que mostra em todos os modos de exibição. Para alterar a aparência dele quando o modo de exibição muda, use o VisualStateManager para aplicar um novo modelo ao ListView.

No SplitPage.xaml, você cria um modelo de ListView semelhante que é usado nas exibições Filled e Snapped, e na exibição FullScreenLandscape se a largura da tela for menor que 1.366 DIPs. Também chama esse modelo de NarrowListItemTemplate e o adiciona à seção de recursos do SplitPage.xaml, logo após o recurso DefaultListItemTemplate.

BR211380.wedge(pt-br,WIN.10).gifPara adicionar um modelo estreito

  1. Clique duas vezes em SplitPage.xaml no Gerenciador de Soluções para abri-lo.
  2. No editor XAML, adicione este XAML da seção Page.Resources após o recurso DefaultListItemTemplate .
    
    
            <!-- green -->
            <SolidColorBrush x:Key="BlockBackgroundBrush" Color="#FF6BBD46"/>
    
            <!-- Used in Filled and Snapped views -->
            <DataTemplate x:Key="NarrowListItemTemplate">
                <Grid Height="80">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Border Background="{StaticResource BlockBackgroundBrush}" 
                            Width="80" Height="80"/>
                    <ContentControl Template="{StaticResource DateBlockTemplate}" 
                                    Margin="-12,-12,0,0"/>
                    <StackPanel Grid.Column="1" HorizontalAlignment="Left" 
                                Margin="12,8,0,0">
                        <TextBlock Text="{Binding Title}" MaxHeight="56" 
                                   Foreground="#FFFE5815" TextWrapping="Wrap"/>
                        <TextBlock Text="{Binding Author}" FontSize="12" />
                    </StackPanel>
                </Grid>
            </DataTemplate>
    
    

Para usar esse modelo de dados, atualize os estados visuais onde ele é usado.

BR211380.wedge(pt-br,WIN.10).gifPara atualizar os estados visuais

  1. No XAML para os estados visuais FilledOrNarrow e Snapped, encontramos a animação que se destina à propriedade ItemTemplate do itemListView.
    Dica   Pressione Ctrl+F para abrir a caixa Localização Rápida e pesquise por "Standard80ItemTemplate" caso tenha problemas para encontrá-lo.
     
  2. Altere o valor para usar o recurso NarrowListItemTemplate, como este: Value="{StaticResource NarrowListItemTemplate}".

    Você usa seu modelo personalizado em vez do recurso Standard80ItemTemplate padrão.

Este é o XAML atualizado para animações.



<VisualState x:Name="FilledOrNarrow">
    <Storyboard>
    ....
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="ItemTemplate">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource NarrowListItemTemplate}"/>
        </ObjectAnimationUsingKeyFrames>
    ....
    </Storyboard>
</VisualState>
...
<VisualState x:Name="Snapped">
    <Storyboard>
    ....
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="ItemTemplate">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource NarrowListItemTemplate}"/>
        </ObjectAnimationUsingKeyFrames>
    ....
    </Storyboard>
</VisualState>

Você também substituiu a seção de detalhes do item da página dividida pela sua própria seção de detalhes que usa uma WebView. Por causa dessa alteração, algumas animações no estado visual Snapped_Detail destinam-se a elementos que não existem mais. Elas causarão erros quando o aplicativo for ajustado; portanto, é preciso removê-las.

BR211380.wedge(pt-br,WIN.10).gifPara remover animações não utilizadas

  • Em SplitPage.xaml, excluímos essas animações do estado visual Snapped_Detail.
    
    
    <VisualState x:Name="Snapped_Detail">
        <Storyboard>
        ...
            <!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetailTitlePanel" Storyboard.TargetProperty="(Grid.Row)">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetailTitlePanel" Storyboard.TargetProperty="(Grid.Column)">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                </ObjectAnimationUsingKeyFrames>-->
       ...
            <!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemSubtitle" Storyboard.TargetProperty="Style">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource CaptionTextStyle}"/>
                </ObjectAnimationUsingKeyFrames>-->
        </Storyboard>
    </VisualState>
    
    

Quando você seleciona um blog e navega para a página dividida no modo ajustado, você pode esperar que a lista de postagens de blog seja mostrada. Em vez disso, o texto da primeira postagem do blog é mostrado porque ele é selecionado por padrão. Para alterar esse comportamento, assegure-se de que nada seja selecionado quando você navega para a página dividida no modo ajustado.

BR211380.wedge(pt-br,WIN.10).gifPara cancelar a seleção do primeiro item

  1. Clique duas vezes em SplitPage.xaml.cs/vb no Gerenciador de Soluções para abri-lo.
  2. No método LoadState, encontre este bloco de códigos.
    
                if (pageState == null)
                {
                    // When this is a new page, select the first item automatically unless logical page
                    // navigation is being used (see the logical page navigation #region below.)
                    if (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View != null)
                    {
                        this.itemsViewSource.View.MoveCurrentToFirst();
                    }
                }
    
    
  3. Adicione a cláusula else, conforme mostrado aqui. A chamada a MoveCurrentToPosition(-1) torna o item atual como não definido.
    
                if (pageState == null)
                {
                    // When this is a new page, select the first item automatically unless logical page
                    // navigation is being used (see the logical page navigation #region below.)
                    if (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View != null)
                    {
                        this.itemsViewSource.View.MoveCurrentToFirst();
                    }
                    else
                    {
                        this.itemsViewSource.View.MoveCurrentToPosition(-1);
                    }
                }
    
    

No DetailPage.xaml, você só precisa ajustar a margem da WebView na exibição Snapped para usar todo o espaço disponível.

BR211380.wedge(pt-br,WIN.10).gif Para atualizar o DetailPage.xaml

  1. Clique duas vezes em DetailPage.xaml no Gerenciador de Soluções para abri-lo.
  2. No XAML do estado visual Snapped, adicionamos uma animação para mudar o valor da propriedade Margin em contentViewBorder.
    
    
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="contentViewBorder" Storyboard.TargetProperty="Margin">
                <DiscreteObjectKeyFrame KeyTime="0" Value="20,5,20,20"/>
            </ObjectAnimationUsingKeyFrames>
    >
    
    

Este é o XAML completo para o estado ajustado.



                <!-- The back button and title have different styles when snapped -->
                <VisualState x:Name="Snapped">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
                        </ObjectAnimationUsingKeyFrames>

                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="contentViewBorder" Storyboard.TargetProperty="Margin">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="20,5,20,20"/>
                        </ObjectAnimationUsingKeyFrames>

                    </Storyboard>
                </VisualState>

Pressione F5 para compilar e executar o aplicativo. Experimente-o em diferentes orientações e modos de exibição.

Gerenciando o ciclo de vida e o estado do aplicativo

Observação   Nesta seção, você aplica os conceitos abordados na Parte 2: Gerenciar o ciclo de vida e o estado do aplicativo. Para saber mais sobre como salvar o estado do aplicativo, reveja a Parte 2.
 

Para conservar os recursos do sistema, ele suspende automaticamente (e eventualmente encerra) os aplicativos da Windows Store executados em segundo plano. Um aplicativo bem projetado pode ser suspenso, encerrado e reiniciado pelo sistema e parecer que estava em execução o tempo todo. Aqui você adiciona um código para manipular a suspensão e retomada do aplicativo. Felizmente, a maior parte da infraestrutura é fornecida pelas classes LayoutAwarePage e SuspensionManager nos modelos do Visual Studio; assim, você só precisa adicionar um pouco de código para salvar e restaurar as configurações.

Gerenciando o estado de navegação

Para usar a classe SuspensionManager para gerenciar o estado do aplicativo, registre o Frame raiz que mantém o conteúdo com o SuspensionManager. Quando o aplicativo é suspenso, você chama SuspensionManager.SaveAsync para salvar o estado de navegação do seu aplicativo, incluindo a página que é a atual e o parâmetro de navegação que foi passado para essa página. Quando o aplicativo é restaurado, o estado de navegação é restaurado e o parâmetro de navegação é passado de volta para a página.

BR211380.wedge(pt-br,WIN.10).gifPara salvar o estado de navegação

  1. Clique duas vezes em App.xaml.cs/vb no Gerenciador de Soluções para abri-lo.
  2. Adicione a palavra-chave async ao método OnSuspending.
    
    private async void OnSuspending(object sender, SuspendingEventArgs e)
    
    
  3. Adicione este código ao método OnSuspending após o comentário "TODO".

    SuspensionManager.SaveAsync salva o estado de navegação do Frame e fornece à Page uma oportunidade de restaurar seu conteúdo.

    
                //TODO: Save application state and stop any background activity
                await WindowsBlogReader.Common.SuspensionManager.SaveAsync();
    
    

Quando o aplicativo é restaurado depois de ser suspenso e encerrado, este código é executado para restaurar o estado de navegação do aplicativo.

BR211380.wedge(pt-br,WIN.10).gifPara carregar o estado de navegação

  1. Em App.xaml.cs/vb, adicione este código ao método OnLaunched imediatamente após a criação de uma instância do novo Frame.

    Aqui você registra o Frame com a classe SuspensionManager.

    
                    // Add this code after "rootFrame = new Frame();"
                    WindowsBlogReader.Common.SuspensionManager.RegisterFrame(rootFrame, "AppFrame");
    
    
  2. Adicione este código ao método OnLaunched após o comentário "TODO".

    SuspensionManager.RestoreAsync restaura o estado de navegação do Frame e fornece à Page uma oportunidade de restaurar seu conteúdo.

    
                        //TODO: Load state from previously suspended application
                        await WindowsBlogReader.Common.SuspensionManager.RestoreAsync();
    
    

Gerenciando o estado da página

Você também precisa salvar quaisquer configurações específicas de página quando o aplicativo é suspenso e restaurado. No aplicativo leitor de blog, só é preciso salvar e restaurar o item selecionado na página dividida. Isso é feito nas substituições dos métodos SaveState e LoadState que são fornecidas pela classe LayoutAwarePage.

BR211380.wedge(pt-br,WIN.10).gifPara salvar o estado da página

  1. Clique duas vezes em SplitPage.xaml.cs/vb no Gerenciador de Soluções para abri-lo.
  2. Adicione este código ao método SaveState após o comentário "TODO".

    A classe SuspensionManager serializa e salva o dicionário pageState em um arquivo XML. Os dados salvos no pageState só são salvos para esta sessão. Aqui, você salva o título da postagem de blog selecionada na lista.

    
                    // TODO: Derive a serializable navigation parameter and assign it to
                    //       pageState["SelectedItem"]
                    if (selectedItem != null)
                    {
                        string itemTitle = ((FeedItem)selectedItem).Title;
                        pageState["SelectedItem"] = itemTitle;
                    }
    
    
    

BR211380.wedge(pt-br,WIN.10).gifPara carregar o estado da página

  • No SplitPage.xaml.cs/vb, adicione este código ao método LoadState após o terceiro comentário "TODO".
    
                        // TODO: Invoke this.itemsViewSource.View.MoveCurrentTo() with the selected
                        //       item as specified by the value of pageState["SelectedItem"]
    
                        string itemTitle = (string)pageState["SelectedItem"];
                        FeedItem selectedItem = FeedDataSource.GetItem(itemTitle);
                        this.itemsViewSource.View.MoveCurrentTo(selectedItem);
    
    

Adicionando uma tela inicial e um logotipo

A primeira impressão que seu aplicativo causa a um usuário vem do logotipo e da tela inicial. O logotipo aparece na Windows Store e na tela inicial. A tela inicial é mostrada instantaneamente quando um usuário inicia o aplicativo e fornece comentários imediatos ao usuário enquanto o aplicativo inicializa seus recursos. Ela é ignorada quando a primeira página do aplicativo está pronta para ser mostrada.

A tela inicial consiste em uma cor de tela de fundo e uma imagem com 620 x 300 pixels. Você define esses valores no arquivo Package.appxmanifest. Clique duas vezes nesse arquivo para abri-lo no editor de manifesto. Na guia Interface de Usuário do Aplicativo do editor de manifesto, você define o caminho da imagem e a cor de tela de fundo da tela inicial. O modelo de projeto fornece uma imagem em branco padrão chamada SplashScreen.png. Você a substitui por sua própria imagem de tela inicial, que identifica claramente seu aplicativo e imediatamente atrai os usuários para ele. Também pode especificar um logotipo substituindo os arquivos de logotipo do modelo por seus próprios arquivos. Aqui está a tela inicial do leitor de blog.

Imagem da tela inicial.

A tela inicial básica funciona bem para o leitor de blog, mas você também pode torná-la mais atraente usando as propriedades e os métodos da classe SplashScreen. Você pode usar a classe SplashScreen para obter as coordenadas da tela inicial e usá-las para posicionar a primeira página do aplicativo. Também é possível descobrir quando a tela inicial é ignorada; assim, você sabe que é hora de iniciar as animações de entrada de conteúdo para o aplicativo.

Ver o código

Você se atrasou ou deseja verificar seu trabalho? Nesse caso, veja o código completo do leitor de blog.

E agora?

Você aprendeu a usar modelos de página internos do Visual Studio Express 2012 para Windows 8 para compilar um aplicativo completo de várias páginas, e também a navegar e passar dados entre as páginas. Aprendeu a usar estilos e modelos para fazer com que seu aplicativo se encaixe na personalidade do site de blogs da equipe do Windows. Também aprendeu a usar animações de tema, uma barra de aplicativos e uma tela inicial para fazer com que seu aplicativo se encaixe na personalidade do Windows 8. Finalmente, você aprendeu a adaptar seu aplicativo a diversos layouts e orientações para que ele sempre fique com a melhor aparência.

Para saber mais sobre o desenvolvimento de aplicativos, veja a lista de recursos de aprendizagem e referência para a criação de aplicativos da Windows Store.

Mapa de aplicativos do Tempo de Execução do Windows em C# ou Visual Basic .

 

 

Mostrar:
© 2017 Microsoft