Vamos fazer um cliente de Twitter???
Vamos!
Ebaaa...
Ok ok, comemorações a parte vamos iniciar.
A ideia aqui é usar a API do Twitter, fazendo simples requisições web, e aproveitar o potencial do XAML, a linguagem de interface por trás do Silverlight (inclusive do Windows Phone) e do WPF.
Então crie uma aplicação utilizando uma dessas tecnologias chamada de “MeuClienteDeTwitter”.
No exemplo foi utilizado WPF. Nossa UI ficará da seguinte maneira:
No “.xaml” principal/inicial (no caso do WPF o “MainWindow.xaml”), desenhe uma tela, arrastando os controles da Toolbox para a tela, com os seguintes controles:
- TextBlock: Ao topo servindo de título para a aplicação. Altere a propriedade “Text” (para definir o valor do mesmo) e as propriedades de fonte, para deixar esse texto mais destacado. Esse controle funciona como uma Label do ASP.NET ou Windows Forms.
- TextBox: Caixa de texto editável. Defina o nome dela como “txtUsuario”, acompanhe na imagem a seguir:
- Button: Botão para fazer a requisição e listar os tweets do usuário informado. Defina seu nome como “btnCarregar”.
- ListBox: Lista de itens. Montaremos um layout para os itens que listaremos. Por hora nomeie-o como “lstConteudo”, e deixe seu fundo transparente, como na imagem abaixo:
Curiosidade: O controle Label existe tanto no WPF como no Silverlight. Mas ele é um ContentControl, o que significa que ele pode conter “qualquer coisa” dentro delae não ficando limitado somente a texto puro e simples. Podemos adicionar um vídeo e imagem dentro da mesma Label, por exemplo. Como nesse exemplo queremos apenas texto para o título, optei pelo TextBlock.
Uma coisa importante quando definimos layout de telas com XAML é ficar atento ao painel de layout. Pois todos os controles são aninhados e organizados em um ou mais painéis. Há vários painéis, cada um com uma forma de organizar o layout diferente. Nesse caso, todos esses controles ficam dentro de uma Grid.
Essa Grid “não tem nada haver” com as conhecidas “DataGrids”, que montam tabelas com linhas e colunas proveniente de uma coleção de dados.
A Grid do XAML é um painel que se orienta por distancia das margens. Por exemplo: se colocarmos um botão em uma Grid, e definirmos ele com uma margem de 20 pixels na esquerda e 20 pixels na direita, não interessa o tamanho da janela ou o quanto ela for redimensionada, o controle se adaptará para manter a distancia das margens, sempre em 20 pixels próximo as bordas laterais.
A Grid pode ser dividida, criando bordas internas. Nesse exemplo, foi definida uma borda logo abaixo do botão e do campo de texto, para separar a ListBox dos demais controles. Assim, após colocar a ListBox na parte inferior, defini as margens dela como zero para todos os lados, logo ela acompanhará o tamanho da janela tanto em largura como em altura.
Bem, o intuito aqui não é ficar discutindo sobre esses painéis, em outra oportunidade eu falo mais dos mesmos.
Vejamos como ficou o XAML então:
<Window x:Class="MeuClienteDeTwitter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="484" Width="385">
<!--Definindo o fundo em gradiente da janela-->
<Window.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="LightBlue" Offset="0" />
<GradientStop Color="White" Offset="1" />
</LinearGradientBrush>
</Window.Background>
<Grid>
<!--Definindo as linhas da grid para o layout.
O "*" representa o tamanho que sobrar da jenala,
após utilizar os 80 da linha de cima-->
<Grid.RowDefinitions>
<RowDefinition Height="80" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Content="Meu Cliente de Twitter" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" FontWeight="Bold" FontSize="16" FontFamily="Verdana" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="12,46,0,0" Name="txtUsuario" VerticalAlignment="Top" Width="213" />
<Button Content="Carregar o Twitter" Height="23" HorizontalAlignment="Left" Margin="231,46,0,0" Name="btnCarregar" VerticalAlignment="Top" Width="124" Click="btnCarregar_Click" />
<ListBox Grid.Row="1" Name="lstConteudo" BorderBrush="{x:Null}" Background="{x:Null}">
<!--Template que define o layout de cada item da ListBox-->
<ListBox.ItemTemplate>
<DataTemplate>
<!--Perceba que foi utilizado um outro painel para definir o layout-->
<StackPanel Orientation="Horizontal" Height="132">
<Image Source="{Binding UrlFoto}" Height="73" Width="73" VerticalAlignment="Top" Margin="0,10,8,0" />
<StackPanel Width="370">
<TextBlock Text="{Binding Usuario}" Foreground="#FFC8AB14" FontSize="28"/>
<TextBlock Text="{Binding Conteudo}" TextWrapping="Wrap" FontSize="23"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
Para fazer o fundo em gradiente, utilizamos o LinearGradientBrush com duas cores definidas para a Janela.
A primeira linha da Grid, que separa a ListBox dos demais controles do “cabeçalho”, tem 80 pixels de altura, o restante, definido como “*”, fica para a segunda linha que é onde está a ListBox.
Agora vem uma parte importante, a definição do layout dos itens que forem carregados no ListBox. Para isso temos que criar um painel de Layout, dentro do template de dados da ListBox.
Nesse caso o painel de layout utilizado foi o StackPanel, ou painel empilhador. Ele empilha os controles, um sobre o outro, seja na vertical ou na horizontal.
Dentro desse painel, colocamos um controle Image, para exibir a foto do usuário, com altura e largura de 73 pixels. Colocamos também dois TextBlock, um para o nome do usuário, com fonte um pouco maior, e outro para o tweet em si, com a quebra de linha ativada (propriedade “TextWrapping="Wrap"”).
Uma outra curiosidade: se você vem do desenvolvimento Windows Forms e quer uma maneira de organizar layout semelhante aos “bons e velhos” formulários, opte pelo painel chamado Canvas.
Ao analisar o XAML uma coisa deve estar te deixando cmo a pulga atrás da orelha: O que são aqueles “bindings”.
O pessoal do ASP.NET deve até desconfiar.
Bem, os bindings são definições de vinculo. Ou seja, nesse caso, passaremos uma lista de objetos para o ListBox. Esses objetos serão do tipo ItemTwitter, que criaremos mais adiante. Ou melhor, vamos cria-lo agora. Clique com o botão direito no projeto > Add > Class. Veja na imagem abaixo:
O nome dela será “ItemTwitter”, o código fonte está abaixo:
namespace MeuClienteDeTwitter
{
public class ItemTwitter
{
public string UrlFoto { get; set; }
public string Usuario { get; set; }
public string Conteudo { get; set; }
}
}
Basicamente três propriedades string estão definidas.
Voltando ao binding, quando passarmos para o ListBox uma lista do tipo ItemTwitter, para cada objeto da lista será criado um item no ListBox. Mas como vincular o layout com as informações dos itens da lista? Definindo um binding no controle e propriedade desejados. No caso da foto, colocaremos no controle Image, na propriedade Source (pois vincularemos a URL da foto do usuário). Nos TextBlocks a propriedade de vinculo será a Text.
No futuro falarei especificamente de binding.
Faltou definir a codificação para tudo funcionar. Então volte para o modo de desing e dê um duplo click no botão, assim será criado o evento click do mesmo.
Em seu click definiremos o seguinte código:
using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Xml.Linq;
namespace MeuClienteDeTwitter
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
// -> Método do evento de click do botão para carregar os tweets.
private void btnCarregar_Click(object sender, RoutedEventArgs e)
{
// -> Criamos um objeto que fará uma requisição web para a API do Twitter.
var requisicao = new WebClient();
// -> Concatenando o nome do usuário digitado na txtUsuario na URL da API do Twitter.
var url = string.Format("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name={0}", txtUsuario.Text);
/*
-> Faremos a requisição web de forma assincrona, ou seja,
* a requisição é disparada a aplicação não ficará travada até ela responder.
* Mas quando ela responder, deve responder para a aplicação com um evento.
* Então temos que definir o evento que ela responderá "requisicao_DownloadStringCompleted".
* Agora podemos fazer a requisição assincrona, passando a URL da API, atravéz da classe URI.
*/
requisicao.DownloadStringCompleted += new DownloadStringCompletedEventHandler(requisicao_DownloadStringCompleted);
requisicao.DownloadStringAsync(new Uri(url));
}
void requisicao_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
// -> Todo o retorno do prossessamento da requisição virá na variável "e".
// -> Verificamos se houve algum erro.
if (e.Error != null)
return;
// -> o Retorno da requisição é um XML. Teste no seu navegador para averiguar.
// Então fazemos um parse nele para utilizar o LINQ.
var tweets = XElement.Parse(e.Result);
// -> Usando o LINQ, tranformamos os nós do XML em uma lista de objetos "ItemTwitter"
var results = from tweet in tweets.Descendants("status")
select new ItemTwitter
{
UrlFoto= tweet.Element("user").Element("profile_image_url").Value,
Conteudo = tweet.Element("text").Value,
Usuario = tweet.Element("user").Element("screen_name").Value
};
// -> Alimenta a ListBox.
lstConteudo.ItemsSource = results.ToList();
}
}
}
Percebam que a API do Twitter nada mais é do que uma chamada HTTP que retorna um XML. Faça o teste no seu Navegador.
Após isso, utilizamos o LINQ para criar objetos, a partir do XML, e com eles alimentamos a ListBox, e está pronto nosso leitor de Tweets.
É praticamente a mesma coisa fazer essa App em Silverlight, inclusive coloca-la dentro de seu Windows Phone, veja aqui o Scott Gu fazendo isso:
http://weblogs.asp.net/scottgu/archive/2010/03/18/building-a-windows-phone-7-twitter-application-using-silverlight.aspx
Espero que tenham gostado.