Windows Phone 7 - dados de OData

Do Renato Haddad

Março 2012

Hh972465.060DE5057573180CEC6D227C6D3E2207(pt-br,MSDN.10).png

Como ler um banco de dados através de um serviço OData?

O Windows Phone 7.5 Mango permite armazenar um banco de dados no próprio celular através do local Database. Sabemos que nos bastidores é usado o SQL Compact 4.0, permitindo você criar uma aplicação para manipular qualquer base de dados e depois sincronizar com um servidor. Mas o foco deste artigo não é armazenar nada local, e sim, solicitar os dados de um serviço que provê os dados através de OData.

OData (Open Data Protocol) é na verdade um serviço que contém uma classe que oferece um conjunto de informações para quem quiser consumir. Os mais conhecidos neste cenário são os famosos Web Services e WCF (Windows Communication Foundation), onde você faz uma referência no seu projeto e pronto, consome qualquer serviço que esteja disponível podendo retornar diversos tipos de dados como uma string, um array, uma coleção, um objeto, enfim, depende da situação.

Existe um banco de dados conhecido de todos no mundo, que é o Northwind e em http://services.odata.org há o serviço que permite ler tais dados para você consumir no Windows Phone 7.5, por exemplo.


Iniciar um projeto

Vamos ao projeto. Primeiro crie um novo projeto de Silverlight for Windows Phone, usando o template Windows Phone Pivot Application chamado ConsomeOData, conforme a seguinte figura. Quando clicar em OK aparecerá a janela questionando qual a versão, então selecione Windows Phone 7.1.

Hh972465.7D4D3F7880EFBBFADE68A6A2ADC9847B(pt-br,MSDN.10).png

Criado o MainPage.xaml

Muito bem, neste momento é criado o MainPage.xaml contendo a estrutura do controle Pivot com dois itens chamados first e second. Como não precisaremos dos dados de exemplo, substitua todo o código por este a seguir.

<Grid x:Name="LayoutRoot" Background="Transparent">
    <!--Pivot Control-->
    <controls:Pivot Title="Ler Northwind OData">
        <!--Pivot item one-->
        <controls:PivotItem Header="categorias">
            <Grid>
                <ListBox Name="lstCategorias">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock Text="{Binding CategoryName}"
                                            Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                                <TextBlock Text="{Binding Description}"
                                            Style="{StaticResource PhoneTextSubtleStyle}"
                                            TextWrapping="Wrap"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </controls:PivotItem>

        <!--Pivot item two-->
        <controls:PivotItem Header="produtos">
            <Grid>
                <ListBox Name="lstProdutos">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock Text="{Binding ProductName}"
                                            Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="Preço: " Style="{StaticResource PhoneTextSubtleStyle}"/>
                                    <TextBlock Text="{Binding UnitPrice}" Style="{StaticResource PhoneTextSubtleStyle}"/>
                                    <TextBlock Text="Estoque: " Style="{StaticResource PhoneTextSubtleStyle}"/>
                                    <TextBlock Text="{Binding UnitsInStock}" Style="{StaticResource PhoneTextSubtleStyle}"/>
                                </StackPanel>
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </controls:PivotItem>
    </controls:Pivot>
</Grid>

PivotItem e Iternamente

Vale dizer que o XAML é apenas o layout. No código anterior temos dois itens PivotItem onde os cabeçalhos (Header) são categorias e produtos. Iternamente cada PivotItem contém um ListBox com um template (DataTemplate) e seus respectivos TextBlock. O ponto chave aqui é o conteúdo das propriedades Text dos controles, os quais apontam para os nomes dos campos nas entidades Categories e Products do banco de dados Northwind. O vínculo será feito usando-se apenas o Binding para os respectivos nomes.

Hh972465.923A8F35EF618D25D40B7959810D44DD(pt-br,MSDN.10).png

Mas, onde está o banco de dados se usaremos um serviço? A primeira coisa a fazer é referenciar o serviço, então, no Solution Explorer clique com o botão direito em References e selecione Add Service Reference. Na janela aberta, digite a URL que contém o serviço sendo http://services.odata.org/Northwind/Northwind.svc. Clique no botão Go e aguarde o retorno dos serviços. Em Namespace digite ServicoDados, tendo uma tela igual com a seguinte.

Hh972465.851A0F210957F6AE2ED3D61713D4727A(pt-br,MSDN.10).png

Clique no botão OK e pronto, o serviço está referenciado e já podemos consumi-lo. Pressione F7 para mostrar a janela de código C# e na lista de using digite os seguintes códigos para podermos usar estes namespaces.

using System.Data.Services.Client;
using ConsomeOData.ServicoDados;

Em seguida, após a declaração da classe MainPage, declare as seguintes linhas referenciando o contexto NorthwindEntities, a Uri do serviço e as duas entidades Category e Product no DataServiceCollection. Todas estas classes nós não criamos, pois estão declaradas na referência do serviço quando adicionados em Add Service Reference. Na dúvida clique em NorthwindEntities e pressione F12.

public partial class MainPage : PhoneApplicationPage
    {
        NorthwindEntities contexto;
        Uri uri = new Uri("http://services.odata.org/Northwind/Northwind.svc");
        DataServiceCollection<Category> categorias;
        DataServiceCollection<Product> produtos;

O próximo passo é comentar a seguinte linha no construtor da classe (public MainPage), o qual usa os dados de exemplo criados no template, e como teremos os nossos dados, comente esta linha.

// DataContext = App.ViewModel;

O mesmo você deverá fazer no evento Loaded da página, comentando as seguintes linhas.

private void MainPage_Loaded(object sender, RoutedEventArgs e)

{

//if (!App.ViewModel.IsDataLoaded)

//{

// App.ViewModel.LoadData();

//}

Após o comentário e dentro do MainPage_Loaded, digite os códigos que serão executados ao carregar a página. Aqui fazemos referência ao contexto contido na respectiva Uri, as categorias e produtos.`

contexto = new NorthwindEntities(uri);

//categorias
categorias = new DataServiceCollection<Category>(contexto);
var cat = from c in contexto.Categories select c;
categorias.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(categorias_LoadCompleted);
categorias.LoadAsync(cat);

//produtos
produtos = new DataServiceCollection<Product>(contexto);
var prod = contexto.Products.OrderBy(p => p.ProductName);
produtos.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(produtos_LoadCompleted);
produtos.LoadAsync(prod);

Veja uma explicação detalhada do bloco que lê todas as categorias usando o LINQ (Language Integrated Query) onde seleciona todas as categorias existentes na entidade Categories.

var cat = from c in contexto.Categories select c;

Como a variável cat contém o resultado, em seguida é disparado o delegate para mostrar os dados passando o cat como parâmetro. O mais interessante é que isto ocorre assíncrono, veja o LoadAsync. Uma dica para a criação do evento, quando você digitar categorias. LoadCompleted e o += imediatamente pressione a tecla TAB que o evento é gerado automaticamente.

categorias.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(categorias_LoadCompleted);
categorias.LoadAsync(cat);

O mesmo ocorre com produtos, no entanto usei uma expressão Lambda que seleciona todos os produtos da entidade Products e ordena pelo nome do produto (ProductName).

var prod = contexto.Products.OrderBy(p => p.ProductName);

Veja a chamda do código assíncrono para produtos.

produtos.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(produtos_LoadCompleted);
produtos.LoadAsync(prod);

Por fim, digite os códigos a seguir para cada método, o qual verifica se produtos ou categorias são diferentes de nulo. Caso verdadeiro, então é feita a leitura parcial para os próximos resultados de dados. Caso contrário, é definida a fonte de dados (ItemsSource) para vincular os controles lstProdutos e lstCategorias a este fonte de dados.

void produtos_LoadCompleted(object sender, LoadCompletedEventArgs e)
{
    if (e.Error == null)
    {
        if (produtos.Continuation != null)
            produtos.LoadNextPartialSetAsync();
        else
            lstProdutos.ItemsSource = produtos;
    }
}

void categorias_LoadCompleted(object sender, LoadCompletedEventArgs e)
{
    if (e.Error == null)
    {
        if (categorias.Continuation != null)
            categorias.LoadNextPartialSetAsync();
        else
            lstCategorias.ItemsSource = categorias;
    }
}

Pronto, o código está finalizado. Agora pressione a tecla F5 para executar o projeto no emulador e conferir o resultado. Certifique-se que o emulador tem conexão com a internet, pois o OData não roda sem isto. Veja que todas as categorias estão mostradas no PivotItem categorias.

Hh972465.BC9270915AFFAC5311884D0F7B8627CC(pt-br,MSDN.10).png

Navegue até o PivotItem produtos e veja a lista de produtos de acordo com o layout que definimos. Obviamente que você pode fazer scroll de tela para visualizar os demais dados.

Hh972465.73BAE0C8668537DEA20FB59DCFECD865(pt-br,MSDN.10).png

Conclusão

Com o conteúdo visto neste artigo você pode criar uma infinidade de aplicações para Windows Phone 7.5 baseadas em serviços. A integração de todas estas tecnologias é muito importante para que você possa ter uma fonte de dados confiável, um banco de dados com diversas informações que serão visualizadas em qualquer tipo de aplicação, como por exemplo, esta criada no artigo. Sempre que for criar uma aplicação para armazenar informações pense em oferecer um serviço, pois o Windows Phone precisa apenas de uma conexão de dados, seja WiFi, 3G ou GPRS.


Renato Haddad é MVP, MCT, MCPD e MCTS, palestrante em eventos da Microsoft em diversos países, ministra treinamentos focados em produtividade com o VS.NET 2010, ASP.NET 4, ASP.NET MVC, Entity Framework, Reporting Services, Windows Phone e Windows 8. Visite o blog http://weblogs.asp.net/renatohaddad

Mostrar: