MSDN Magazine > Home > Issues > 2007 > June >  SILVERLIGHT: Comece a criar uma experiênci...
SILVERLIGHT
Comece a criar uma experiência mais profunda na Web
Laurence Moroney

Este artigo é baseado em uma versão de pré-lançamento do Silverlight. Todas as informações contidas neste documento estão sujeitas a alterações.
Este artigo aborda:
  • Uma introdução ao Silverlight e ao XAML
  • Criando um aplicativo simples do Silverlight
  • Gerando dinamicamente aplicativos do Silverlight no servidor
  • Criando um serviço XAML
Este artigo utiliza as seguintes tecnologias:
Silverlight, XAML, JavaScript
Faça o download do código deste artigo:: Silverlight2007_06.exe (300 KB)
Procurar código online
Um dos componentes essenciais da estratégia da Microsoft para o desenvolvimento na Web de próxima geração é uma nova tecnologia denominada Microsoft® Silverlight™, que anteriormente tinha o codinome "WPF/E". Projetado para trazer a experiência do Windows® Presentation Foundation para a Web, o Silverlight proporciona um conteúdo sofisticado e interativo perfeitamente adequado ao restante do ambiente de desenvolvimento na Web, inclusive o ASP.NET AJAX.
Para alcançar amplamente a comunidade da Web, o Silverlight precisa ser executado com sucesso em alguns sistemas operacionais populares e nos navegadores mais populares. Por isso, a primeira versão oferece suporte aos navegadores Firefox e Safari, executados no Mac OS X, e também a Firefox e Internet Explorer®, executados no Windows. Mais sistemas operacionais e navegadores terão suporte com a evolução do produto. Além desses recursos, o Silverlight é totalmente auto-suficiente e não tem dependências em relação a outros produtos, como o Windows Media® Player para a reprodução de vídeo ou o Microsoft .NET Framework 3.0 para a análise de XAML.
Neste artigo, você terá uma visão geral de alto nível da arquitetura do Silverlight, além de experiência prática na criação de vários aplicativos do Silverlight, começando com um aplicativo "Hello World" básico. Em seguida, vou orientá-lo na criação de um media player simples. Você verá também como o Silverlight, sendo uma tecnologia do lado do cliente, se ajusta a um cenário mais amplo orientado a servidores, podendo inclusive ser usado em servidores que executem PHP ou Java.

Apresentando o Silverlight
Essencialmente, o Silverlight é um plug-in de navegador que processa XAML, expondo seu DOM (modelo de objeto de documento) interno e seu modelo de eventos ao navegador de forma programável. Assim, um designer pode reunir um documento XAML contendo gráficos, animações e linhas do tempo e um desenvolvedor pode conectá-lo ao código de uma página para implementar a funcionalidade. Como o XAML se baseia em XML, o documento que define a interface do usuário baixada para o cliente é baseado em texto e, portanto, amigável com mecanismos de busca e firewalls. Além disso, o XAML pode ser montado e emitido em tempo de execução por um aplicativo de servidor, proporcionando uma experiência gráfica não apenas avançada, mas também altamente personalizável e dinâmica.
A anatomia de um aplicativo simples do Silverlight, usando um arquivo XAML estático para definir sua interface do usuário e o JavaScript para a manipulação de eventos, é mostrada na Figura 1. O navegador instancia o plug-in e, como parte do processo, carrega o arquivo XAML. Os eventos nesse arquivo, como clicar em um botão, são capturados pelo navegador e processados pelo JavaScript. Conforme o DOM do conteúdo do Silverlight é exposto, o código JavaScript pode também atualizar dinamicamente o conteúdo do Silverlight, alterando o estado do conteúdo processado.
Figura 1 Aplicativo de exemplo 
A arquitetura que oferece suporte ao aplicativo do Silverlight é mostrada na Figura 2. A interface de programação principal é a API do DOM JavaScript. Isso lhe permite responder a eventos gerados no XAML do Silverlight (como quando termina o carregamento do conteúdo ou quando uma animação é concluída). Você pode também chamar métodos para manipular a apresentação (como iniciar uma animação ou pausar uma reprodução de vídeo). O que atua nos bastidores é o mecanismo de análise de XAML. O analisador cria o DOM XAML na memória para ser usado pelo núcleo da apresentação, que manipula o processamento das animações e dos gráficos definidos pelo XAML. Além disso, o tempo de execução contém os codecs necessários para reproduzir conteúdo multimídia WMV, WMA e MP3.
Figura 2 Arquitetura do Silverlight 
Por fim, o tempo de execução contém o núcleo da apresentação, que gerencia o processamento. Esse tempo de execução da apresentação é incorporado a um plug-in de navegador que oferece suporte a várias versões do Windows e do Mac OS X, usando uma das várias opções de navegador, conforme abordado anteriormente. O resultado final é um mecanismo de processamento de gráficos e mídia auto-suficiente, que pode ser conectado ao navegador e programado via JavaScript.

Visão geral do XAML
O XAML, uma linguagem baseada em XML, pode ser usado para definir recursos gráficos, interfaces do usuário, comportamentos, animações e muito mais. Foi introduzido pela Microsoft como a linguagem de marcação usada no Windows Presentation Foundation, uma tecnologia orientada a desktops que faz parte do .NET Framework 3.0, e projetado para ajudar a fazer a ligação entre o trabalho de designers e desenvolvedores na criação de aplicativos.
Tradicionalmente, os designers usavam um conjunto de ferramentas e recursos para criar um aplicativo e os desenvolvedores usavam ferramentas separadas. Essa incompatibilidade entre conjuntos de ferramentas tinha o potencial de afetar negativamente o aplicativo resultante. A Microsoft introduziu o novo conjunto de ferramentas Expression, particularmente o Microsoft Expression® Design e o Microsoft Expression Blend, para permitir aos profissionais de design reunir, respectivamente, artefatos gráficos e interfaces do usuário. O resultado final, expresso como XAML, pode ser utilizado por um desenvolvedor na criação de um aplicativo.
O XAML usado pela primeira versão do Silverlight é diferente daquele usado pelo Windows Presentation Foundation. O primeiro é um subconjunto orientado à Web do XAML completo disponível para o desktop. Assim, se você já está familiarizado com o XAML do Windows Presentation Foundation, perceberá a ausência de alguns elementos, como a marca <Window>, os recursos de páginas, a ligação de dados e o modelo de controle avançado.
No XAML, você define os elementos usando marcas XML. No nível raiz de cada documento do Silverlight, há uma marca Canvas, que define o espaço onde os elementos da interface do usuário serão desenhados. Essa Canvas deve conter as declarações de namespace XML necessárias para o Silverlight.
<Canvas
    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”>
</Canvas>
Uma Canvas pode ter um ou mais filhos, inclusive Canvases filho que podem criar seus próprios filhos. Os filhos de uma Canvas têm posições relativas à sua Canvas pai, e não à Canvas raiz. Eis um exemplo de Canvas contendo um Rectangle, sendo que o retângulo está posicionado a 25 pixels do canto superior esquerdo de seu pai.
<Canvas Width=”250” Height=”200”>
  <Rectangle Canvas.Top=”25” Canvas.Left=”25” 
       Width=”200” Height=”150” Fill=”Black” />
</Canvas>

Por dentro do XAML
O XAML do Silverlight oferece suporte a diversas formas que podem ser orquestradas, constituindo objetos complexos. As formas básicas com suporte são Rectangle, Ellipse, Line, Polygon, PolyLine e Path. A maioria é auto-explicativa. A PolyLine permite definir uma série de segmentos de linha unidos. O Path permite definir um caminho não-linear (como um rabisco) na Canvas.
Os pincéis determinam como os objetos são pintados na tela. Seu conteúdo é pintado usando um Fill, e os contornos, usando um Stroke. Há pincéis de cores sólidas, em dégradé e de imagens. Os pincéis de cores sólidas são implementados com o uso de uma cor fixa no atributo de preenchimento (como Fill="Black", usado no exemplo anterior), ou usando SolidColorBrush como uma propriedade anexada, assim:
   <Rectangle Canvas.Top=”25” Canvas.Left=”25” 
          Width=”200” Height=”150”>
      <Rectangle.Fill>
         <SolidColorBrush Color=”Black” />
      </Rectangle.Fill>
   <Rectangle>
As cores podem ser definidas pelo nome (há suporte para 141 nomes de cores) ou por definição RGB hexadecimal.
Os pincéis em dégradé são implementados com a definição de um intervalo de dégradé e de um número de interrupções do dégradé em um espaço normalizado. Digamos, por exemplo, que você queira um dégradé linear que se mova da direita para a esquerda, indo de preto para branco e passando pelos tons de cinza. Você deve especificar uma interrupção do dégradé em 0 (o início de uma linha normalizada), que é preto, e uma interrupção do dégradé em 1 (o final de uma linha normalizada), que é branco. O Silverlight pintará o dégradé para você. Também é possível pintar dégradés em espaços bidimensionais, com um retângulo normalizado definindo o espaço (0,0 é o canto superior esquerdo e 1,1 é o canto inferior direito). Dessa forma, para definir um retângulo preenchido com um dégradé 2D tendo vermelho no canto superior esquerdo, preto no canto inferior direito e uma gradação suave entre eles, você usaria o XAML assim:
<Rectangle Width=”200” Height=”150” >
  <Rectangle.Fill>
    <LinearGradientBrush StartPoint=”0,0” EndPoint=”1,1”>
      <LinearGradientBrush.GradientStops>
        <GradientStop Color=”Red” Offset=”0” />
        <GradientStop Color=”Black” Offset=”1” />
      </LinearGradientBrush.GradientStops>
    </LinearGradientBrush>
  </Rectangle.Fill>
</Rectangle>
Os objetos também podem ser pintados usando ImageBrushes, e a imagem será recortada ou alongada como for adequado. Por exemplo, você pode especificar o preenchimento de uma Ellipse usando uma ImageBrush com o XAML da seguinte forma:
<Ellipse Width=”200” Height=”75” >
  <Ellipse.Fill>
    <ImageBrush ImageSource=”http://.../logo.jpg” /> 
  </Ellipse.Fill>
</Ellipse>
É possível processar texto em XAML usando a marca TextBlock. Isso permite o controle sobre aspectos do texto como conteúdo, fonte, tamanho, quebra automática de texto e muito mais. Eis alguns exemplos:
<TextBlock>Hello</TextBlock>

<TextBlock FontSize=”18”>Hello</TextBlock>

<TextBlock FontFamily=”Courier New”>Hello</TextBlock>

<TextBlock TextWrapping=”Wrap” Width=”100”>
  Hello there, how are you?
</TextBlock>
Além disso, o Silverlight oferece suporte a eventos de teclado que podem ser usados para implementar a entrada de texto. Você pode definir um evento de teclado (KeyDown ou KeyUp) no elemento raiz e usar os argumentos do evento para derivar a tecla pressionada.

Transformações, mídia e animações
O XAML permite definir diversas transformações em objetos. RotationTransform gira o elemento por uma quantidade definida de graus, ScaleTransform pode ser usado para alongar ou reduzir um objeto, SkewTransform o inclina em uma direção definida em uma medida definida, TranslateTransform move um objeto de acordo com um vetor definido e MatrixTransform pode combinar todas as ações mencionadas.
As transformações podem ser agrupadas, de forma que um objeto contenha determinado número de transformações, definidas como parte do grupo. A Figura 3 mostra um exemplo. Nesse caso, há três Ellipses na Canvas. Como a transformação é definida no nível da Canvas, cada uma das Ellipses será girada e dimensionada.
<Canvas xmlns=”...” xmlns:x=”...”>
  <Canvas.RenderTransform>
    <TransformGroup>
      <RotateTransform Angle=”-45” CenterX=”50” CenterY=”50”/>
      <ScaleTransform ScaleX=”1.5” ScaleY=”2” />
    </TransformGroup>
  </Canvas.RenderTransform>
  <Ellipse Width=”100” Height=”100” Fill=”Yellow” />
  <Ellipse Canvas.Top=”25” Canvas.Left=”25” Width=”10” Height=”10” 
           Fill=”Black” />
  <Ellipse Canvas.Top=”25” Canvas.Left=”65” Width=”10” Height=”10” 
           Fill=”Black” />
</Canvas>
O conteúdo de áudio e vídeo é controlado com o uso da marca MediaElement. Essa marca usa um atributo de origem que aponta para a mídia a ser reproduzida. Um objeto definido com o uso dessa marca fornece vários métodos e eventos que controlam a reprodução de mídia. Mais adiante neste artigo, você verá um exemplo de media player simples, criado usando XAML, com o JavaScript ativando a interação do usuário (reproduzir, pausar, interromper e assim por diante). Definir um MediaElement é muito simples:
<Canvas xmlns=”...” xmlns:x=”...”>
   <MediaElement Source=”xbox.wmv” /> 
</Canvas>
As animações em XAML são implementadas definindo-se como as propriedades devem ser modificadas ao longo do tempo, por meio de uma linha do tempo. As definições das animações são contidas em um Storyboard. Existem vários tipos diferentes de animações, incluindo DoubleAnimation, que altera as propriedades numéricas; ColorAnimation, que altera cores e pincéis; e PointAnimation, que altera valores bidimensionais. Essas animações podem ser lineares ou baseadas em quadros-chave. Uma animação linear se modifica suavemente ao longo de uma linha do tempo definida. Já uma animação baseada em quadros-chave pode se mover entre valores distintos ao longo do processo.
A Figura 4 mostra um exemplo de uma animação simples que altera a largura de um círculo ao longo do tempo. A propriedade AutoReverse é definida como True, instruindo o mecanismo a continuar a animação, que é revertida em determinado ponto, de forma que o círculo passe de estreito para largo, em vez de repetir a transformação de largo para estreito.
<Canvas xmlns=”...” xmlns:x=”...”>
  <Canvas.Triggers>
    <EventTrigger RoutedEvent=”Canvas.Loaded”>
      <BeginStoryboard>
        <Storyboard> 
          <DoubleAnimation 
            Storyboard.TargetName=”theCircle” 
            Storyboard.TargetProperty=”Width” 
            From=”200” To=”1” Duration=”0:0:2”        
            AutoReverse=”True”/>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Canvas.Triggers>
  <Ellipse x:Name=”theCircle” Width=”100” Height=”100” Fill=”Yellow” />
</Canvas>

Um aplicativo simples do Silverlight
Com o Visual Studio 2005, você pode usar um modelo de aplicativo para o Silverlight (parte do download do SDK do Silverlight) que permite criar facilmente aplicativos para o Silverlight. Para este artigo, usei o aplicativo Visual Web Developer™ Express, disponível para download no MSDN®.
Esse exemplo é um media player muito simples, que reproduz conteúdo de vídeo WMV. Ele usa um vídeo do Channel 9 (channel9.msdn.com), mas você pode mudar isso e reproduzir o vídeo que preferir. O XAML é bastante direto e pode ser visto de forma completa na Figura 5. Para simplificar, elementos TextBlock são usados para os botões Play, Stop e Pause.
<Canvas 
    xmlns=”http://schemas.microsoft.com/client/2007”
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
    Loaded=”javascript:root_Loaded”>

    <MediaElement 
        x:Name=”mPlayer” Width=”640” Height=”400” 
        Source=”http://download.microsoft.com/download/6/5/2/6527a090-aef4-4ed2-8d7e-8946e94257a0/WM_IN_Sumit_Chauhan.wmv” />

    <TextBlock Canvas.Top =”0” Text=”Play” 
        MouseLeftButtonDown=”javascript:PlayVideo”>
    </TextBlock>
    <TextBlock Canvas.Top =”16” Text=”Stop” 
        MouseLeftButtonDown=”javascript:StopVideo”>
    </TextBlock>
    <TextBlock Canvas.Top =”32” Text=”Pause” 
        MouseLeftButtonDown=”javascript:PauseVideo”>
    </TextBlock>
</Canvas>
A marca MediaElement é usada para definir o vídeo. Ela recebe um nome, mPlayer, e tem suas dimensões definidas como 640×400. A marca Source é apontada para um vídeo WMV hospedado como um download no site da Microsoft.
A seguir, vêm os três elementos TextBlock usados para definir os botões Play, Stop e Pause. Esses botões são espaçados verticalmente no canto superior esquerdo da tela. Observe que Canvas.Left não é definida e seu padrão é 0. Esses elementos TextBlock definem um manipulador de eventos JavaScript que será acionado quando forem clicados (MouseLeftButtonDown). Quando o botão do mouse é pressionado sobre eles, o Silverlight passa o evento para o navegador, onde é capturado e manipulado pelo JavaScript.
Vamos agora criar um aplicativo que use esse XAML e implemente os manipuladores de eventos JavaScript usando o Visual Web Developer Express. Para que isso funcione, você precisará do arquivo silverlight.js, que pode ser obtido ao baixar o SDK do Silverlight ou em qualquer exemplo do Silverlight no site de download de exemplos no MSDN.
Usando o Visual Web Developer Express, crie um novo site da Web. Nesse site, crie uma pasta chamada \js e adicione a ela o arquivo silverlight.js. Clique com o botão direito do mouse na pasta \js e selecione Add New Item (Adicionar Novo Item). Selecione JScript File (Arquivo JScript) na caixa de diálogo do novo arquivo e chame-o de eventhandlers.js.
Em seguida, clique com o botão direito do mouse no projeto no Solution Explorer, clique em Add New Item e crie um novo arquivo XML denominado videoplayer.xaml. Preencha-o com o XAML listado na Figura 5.
Por fim, acrescente uma nova página HTML ao projeto e chame-a de Default.htm. Edite a página HTML de forma que carregue as bibliotecas JavaScript e as utilize para criar uma instância do player do Silverlight que irá processar o conteúdo XAML. A Figura 6 mostra o código-fonte completo para Default.htm.
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” 
    “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >
<head>
    <title>Untitled Page</title>
    <script type=”text/javascript” src=”js/silverlight.js”></script>
    <script type=”text/javascript” src=”js/eventhandlers.js”></script>
</head>
<body>
    <form>
         <div id=”AgControl1Host” style=”background:#FFFFFF”>     
            <script type=”text/javascript”>
                Sys.Silverlight.createObjectEx(
                    {source: ‘videoplayer.xml’, 
                     parentElement:’AgControl1Host’, 
                     Id:’AgControl1’, 
                     properties:{
                         width:’1024’, 
                         height:’530’, 
                         background:’white’, 
                         isWindowless:’false’, 
                         framerate:’24’, 
                         version:’0.8.5’}, 
                     events:{onError:null, onLoad:null, 
                         onNotInstalled:null}, 
                     context:null});
            </script>
         </div>
    </form>
</body>
</html>
As marcas de script na parte superior da página importam suas bibliotecas JavaScript, silverlight.js e eventhandlers.js. A biblioteca silverlight.js gerencia o download e a instalação do plug-in do Silverlight. Ela contém as abstrações do navegador e do sistema operacional, por isso você não precisa se preocupar com elas; pode simplesmente implementar um novo controle do Silverlight com a função Sys.Silverlight.createObjectEx. O próprio plug-in do Silverlight deve estar em um bloco DIV que recebe uma ID. Nesse caso, a DIV contendo o plug-in é denominada AgControl1Host. Você usará essa ID ao instanciar o conteúdo do Silverlight.
O plug-in do Silverlight é instanciado com a criação de uma nova instância do controle do Silverlight, sendo necessário passar vários parâmetros para construí-la. Consulte a SDK do Silverlight para obter mais informações sobre esses parâmetros.
A etapa final consiste em implementar as funções JavaScript que manuseiam os eventos gerados ao clicar nos botões Play, Stop e Pause. Esse código deve ser colocado em eventhandlers.js.
function PlayVideo(sender,args)
{
   var mPlayer = sender.findName(“mPlayer”);
   mPlayer.Play();
}
function PauseVideo(sender,args)
{
   var mPlayer = sender.findName(“mPlayer”);
   mPlayer.Pause();
}
function StopVideo(sender,args)
{
   var mPlayer = sender.findName(“mPlayer”);
   mPlayer.Stop();
}
No XAML, o TextBlock Stop definiu que o atributo MouseLeftButtonDown apontaria para JavaScript:StopVideo. Você implementa a função criando uma função JavaScript com o mesmo nome, que use os parâmetros de remetente e argumentos. Você pode usar a função findName no Silverlight para localizar um elemento no DOM que corresponda ao parâmetro nomeado. Assim, para interromper a reprodução do vídeo, você usa a API findName para localizar o MediaElement. No XAML, esse elemento foi denominado mPlayer. A API findName retornará uma referência a esse objeto que você poderá carregar em uma variável JavaScript. Agora que já tem uma referência, você pode simplesmente chamar seu método Stop para interromper a reprodução do vídeo. As funcionalidades Play e Pause são semelhantes.
E está pronto! Um player de vídeo simples criado rapidamente com o Silverlight. Execute o aplicativo e você verá algo parecido com a Figura 7.
Figura 7 O player de vídeo simples (Clique na imagem para aumentar a exibição)
Isso é muito bom se o que você quer é codificar o URI do vídeo no seu XAML, mas, na verdade, não é o caso de uso mais viável. Vejamos agora como mudar isso, passando de uma página HTML estática para um formulário da Web ativo, capaz de aceitar o vídeo como um parâmetro.
A primeira etapa consiste em remover a referência ao arquivo de mídia do XAML. Altere o MediaElement do seu XAML para remover o atributo Source. Deverá ter a seguinte aparência quando você terminar:
<MediaElement x:Name=”mPlayer” Width=”640” Height=”400”/>
Em seguida, crie um novo formulário da Web (ASPX) denominado VideoPlayer.aspx no seu aplicativo. Esse formulário deve instanciar um controle do Silverlight com origem em videoplayer.xaml, como foi feito na Figura 6. Além disso, deve conter o seguinte código JavaScript:
<script type=”text/javascript”>
  function root_Loaded(sender,args) {
    var mPlayer = sender.findName(“mPlayer”);
    mPlayer.Source =
      “<% Response.Write(Request.Params[“VideoURI”]); %>”;
    mPlayer.Play();
}
</script>
O XAML contém uma declaração de evento para que um evento seja acionado quando a Canvas for carregada. Isso é capturado pelo manipulador de eventos root_Loaded no JavaScript. Essa função usa o ASP.NET para extrair o VideoURI da solicitação HTTP no servidor e usa o VideoURI para preencher a função JavaScript, definindo assim a origem do vídeo. Quando a página for executada, o vídeo (no parâmetro VideoURI) será processado pelo Silverlight. Tenha cuidado para que esse exemplo muito simples não tenha filtragem ou tratamento de erros, que devem ser acrescentados se você quiser esse tipo de função nos seus aplicativos.
Observe que, quando você chamar a página com um URI como este:
http://localhost/MSDN1/
VideoPlayer.aspx?videouri=xbox.wmv
O ASP.NET emitirá uma página contendo um bloco JavaScript com a seguinte aparência:
   <script type=”text/javascript”>
     function root_Loaded(sender,args)
     {
       var mPlayer = 
         sender.findName(“mPlayer”);
       mPlayer.Source = “xbox.wmv”;
       mPlayer.Play();
     }
   </script>
Esse JavaScript carrega então o arquivo xbox.wmv no MediaElement e o Silverlight reproduz o vídeo. Isso mostra que usar páginas ativas do lado do servidor (ASPX, PHP ou Java) pode aprimorar muito as experiências dos usuários finais com o Silverlight, tornando-as muito mais flexíveis.

Aplicativos de servidor com o Silverlight
Não é justo pensar no Silverlight somente como uma tecnologia cliente destinada a incorporar conteúdo avançado no navegador. Esse conteúdo avançado já é possível, graças ao uso de plug-ins fechados criados como miniaplicativos Java, controles ActiveX® ou aplicativos do Flash. Por sua vez, o Silverlight é uma tecnologia aberta, no sentido de que a interface do usuário é definida em XAML baseado em texto e a capacidade de programação é obtida com uso de JavaScript. Isso permite aos desenvolvedores criar facilmente aplicativos que interagem com os servidores back-end.
Imagine, por exemplo, um aplicativo meteorológico. Se você quisesse produzir um aplicativo meteorológico do lado do cliente, poderia criar um miniaplicativo Java, um controle ActiveX ou um aplicativo do Flash que consumisse um Web Service e depois implantar o miniaplicativo no cliente. No entanto, isso aumentaria as necessidades de comunicação entre o cliente e o servidor. E se a fonte de dados fosse um serviço com assinatura paga? O responsável por implantar o aplicativo precisaria assumir a tarefa de autenticar licenças para todos os clientes que acessassem o serviço de dados, tomando o tempo que deveria ser dedicado à criação de uma lógica de negócios específica para o domínio.
Contudo, se o aplicativo puder ser montado do lado do servidor e todos os dados forem passados ao cliente, essa tarefa será aliviada. Usando uma ferramenta como o Expression Blend, é possível montar um modelo para a interface do usuário do aplicativo e expressá-lo em XAML. O desenvolvedor então, em tempo de execução, insere os dados relevantes no modelo, retornando o XAML concluído ao cliente, que o processa. Não é necessária nenhuma lógica ou conectividade do lado do cliente (além da conectividade inicial ao servidor que o atende, logicamente), e a implantação e o gerenciamento do cliente se mantêm relativamente fáceis.

Criando um aplicativo meteorológico
Nesta seção, você verá como criar um arquivo XAML simples para implementar um aplicativo meteorológico (veja a Figura 8). O aplicativo meteorológico concluído processará três dias de previsões de temperatura para um CEP específico passado ao aplicativo como parâmetro em seu endereço no navegador. Também processará uma representação gráfica do clima, as datas corretas, o nome do local especificado pelo CEP e animações dos dados meteorológicos. A listagem completa do XAML para o aplicativo meteorológico está disponível no site da MSDN Magazine.
Figura 8 Aplicativo meteorológico do Silverlight  (Clique na imagem para aumentar a exibição)
A marca Canvas de abertura está na parte superior do documento. É um contêiner básico no qual você desenhará seus objetos. Você não está limitado a uma Canvas, e faz sentido que agrupe seus elementos relacionados usando uma. Por exemplo, cada dia contém um gráfico, uma temperatura máxima, uma temperatura mínima e vários rótulos, e tudo isso é coletado em um modelo XAML. A Figura 9 é um exemplo de um dia específico. Nesse caso, a Canvas contém determinado número de TextBlocks e um controle Image. Essa tela foi denominada cnv2 e posicionada com uma opacidade 0 (o que significa que é inicialmente invisível). A altura, a largura, o lado esquerdo e a parte superior foram definidos para posicioná-la em um local específico.
<Canvas x:Name=”cnv2” Width=”624” Height=”101” Opacity=”0” 
        Canvas.Left=”8” Canvas.Top=”165”>

<TextBlock x:Name=”lblDate2” Width=”513” Height=”26” Canvas.Left=”97” FontFamily=”Tahoma” FontSize=”20” FontWeight=”Bold” Foreground=”#FF24AB46” Text=”Wednesday, December 18, 2006” TextWrapping=”Wrap”/>

<TextBlock x:Name=”lblHigh2” Width=”70” Height=”59” Canvas.Left=”112” Canvas.Top=”30” FontFamily=”Tahoma” FontSize=”48” FontWeight=”Bold” Foreground=”#FFF64F12” Text=”27” TextWrapping=”Wrap”/>

<TextBlock x:Name=”lblDegHigh2” Width=”62” Height=”59” FontFamily=”Tahoma” FontSize=”48” FontWeight=”Bold” Foreground=”#FFF64F12” Text=”°F” TextWrapping=”Wrap” Canvas.Left=”172” Canvas.Top=”30”/>

<TextBlock x:Name=”lblLow2” Width=”71” Height=”59” FontFamily=”Tahoma” FontSize=”48” FontWeight=”Bold” Foreground=”#FF444DB5” Text=”27” TextWrapping=”Wrap” Canvas.Left=”265” Canvas.Top=”30”/>

<TextBlock x:Name=”lblDegLow2” Width=”67” Height=”59” FontFamily=”Tahoma” FontSize=”48” FontWeight=”Bold” Foreground=”#FF444DB5” Text=”°F” TextWrapping=”Wrap” Canvas.Left=”327” Canvas.Top=”30”/>

<Image x:Name=”imgWeather2” Width=”97” Height=”87” Canvas.Top=”4” Source=”http://www.nws.noaa.gov/weather/images/fcicons/ra80.jpg” Stretch=”Uniform”/>

</Canvas>
Os TextBlocks são usados para processar texto no Silverlight. Há vários deles aqui e alguns são usados como rótulos codificados, como os rótulos "°F" armazenados nos TextBlocks denominados lblDegHigh2 e lblDegLow2. Consulte o atributo x:Name para localizar o nome.
Os TextBlocks denominados lblDate2, lblHigh2 e lblLow2 contêm informações de espaço reservado – agora estão codificados para dados e temperaturas específicos, mas seu código ASP.NET os substituirá com a data e as temperaturas dinâmicas para o CEP especificado.

Definição de fade in das animações
Um nó de Canvas oferece suporte a disparadores que geram ações em resposta a um evento. Nesse caso, os Canvas.Triggers são especificados para ocorrer quando a página é carregada, como mostrado aqui:
<Canvas.Triggers>
  <EventTrigger RoutedEvent=”FrameworkElement.Loaded”>
    <BeginStoryboard>
...
Dessa forma, quando a página for carregada, os disparadores serão acionados e o Storyboard da animação começará. O Storyboard define os comportamentos da animação. Eis aqui a animação usada na Canvas (contendo os espaços reservados para texto e o gráfico climático de um dia específico) denominada cnv1:
<DoubleAnimationUsingKeyFrames BeginTime=”00:00:00”  
    Storyboard.TargetName=”cnv1” 
    Storyboard.TargetProperty=”(UIElement.Opacity)”>
  <SplineDoubleKeyFrame KeyTime=”00:00:00” Value=”0”/>
  <SplineDoubleKeyFrame KeyTime=”00:00:01” Value=”1”/>
</DoubleAnimationUsingKeyFrames>
O tipo de animação é DoubleAnimationUsingKeyFrames. Você corrigirá a opacidade (definida por UIElement.Opacity) da Canvas e de seus filhos de 0 para 1, causando o fade in dentro de determinado período. O tempo é definido pelos quadros chave associados à animação.
Quando o XAML é processado, o Storyboard começa, causando o fade in da opacidade do primeiro elemento de 0 para 1 entre o início do processamento (tempo de 0 segundos) e 1 segundo depois. Olhe para o XAML e você verá que o fade in das outras telas acontece entre 1 e 2 segundos e entre 2 e 3 segundos respectivamente, gerando o efeito de aparecimento de uma por vez.
O XAML é uma forma válida de XML, por isso os elementos podem ser nomeados com atributos e endereçados a partir dessa nomeação. Assim, por exemplo, o elemento de espaço reservado para a temperatura máxima do primeiro dia tem a seguinte aparência:
<TextBlock x:Name=”lblHigh1” Width=”67” Height=”59” 
        Canvas.Left=”112” Canvas.Top=”30” FontFamily=”Tahoma” 
        FontSize=”48” FontWeight=”Bold” Foreground=”#FFF64F12” 
        Text=”27” TextWrapping=”Wrap”/>
Esse TextBlock foi denominado lblHigh1. O serviço (que você verá na próxima etapa) usa um XMLDocument para carregar o modelo de XAML, localizar o nó com esse nome e alterar sua propriedade de texto com um código C# que tem a seguinte aparência:
string xpath = “//d:TextBlock[@x:Name=’lblHigh1’]”;
xNode = xmlDoc.SelectSingleNode(xpath, mng);
string high = myResults[n - 1].MaxTemperatureF;
xNode.Attributes[“Text”].Value = high;

Criando um serviço XAML
Quando você usa o Silverlight em uma página da Web, um dos parâmetros usados pelo controle é a localização do XAML a ser processado. Nesse caso, o XAML é dinâmico, mudando com base no CEP para o qual é solicitada a previsão meteorológica. Dessa forma, você criará um aplicativo Web capaz de gerar e retornar o XAML, e a página que o processa consultará essa página. Essa é a primeira etapa de criação do aplicativo do Silverlight.
Usando o Visual Studio®, crie um novo projeto da Web. Adicione uma pasta \js contendo silverlight.js, como você fez com o player de vídeo anterior. Adicione uma nova referência da Web ao projeto, fazendo referência ao Web Service definido em:
http://www.webservicex.net/WeatherForecast.asmx?WSDL
Dê ao serviço o nome de weatherservice. Adicione um novo formulário da Web ao projeto e denomine-o XAMLSource.aspx. Selecione a opção Add Code as a Separate Page (Adicionar Código como uma Página Separada). Verifique se a parte superior da página de código contém o seguinte conjunto de diretivas de uso:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Xml.XPath;
Você acrescentará código ao manipulador de eventos Page_Load em XAMLSource.aspx durante o restante desta seção. Primeiro, carregue o modelo (denominado Scene.xaml) em um objeto XMLDocument:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(Server.MapPath(“Scene.xaml”));
Em seguida, configure o parâmetro de leitura. Você chamará a página usando um parâmetro de cadeia de caracteres de consulta especificando o CEP necessário:
http://server/XamlSource.aspx?ZIP=<something>
Para recuperar o parâmetro, use este código:
string strZip = “98052”;
if (Request.Params[“ZIP”] != null)
    strZip = Request.Params[“ZIP”];
Isso iniciará a cadeia de caracteres que irá manter o CEP parametrizado localmente e defini-lo como padrão, se não for passado como parte da solicitação HTTP. Em seguida, crie a chamada para o Web Service que fornece as informações meteorológicas:
weatherservice.WeatherForecast myWeather = new 
    weatherservice.WeatherForecast();

weatherservice.WeatherForecasts myForecast =   
    myWeather.GetWeatherByZipCode(strZip);

weatherservice.WeatherData[] myResults = myForecast.Details;
Esse código cria uma instância do proxy do Web Service (criado para você pelo Visual Studio, ao adicionar uma referência ao WSDL do serviço) que ele chama de myWeather. O Web Service retorna dados na estrutura de dados WeatherForecasts, por isso cria uma instância dessa estrutura de dados (denominada myForecast) chamando o método GetWeatherByZipCode no serviço e passando-lhe uma cadeia de caracteres. Como o membro Details do objeto de previsão é uma matriz de tipos de WeatherData, a variável myResults é configurada como uma instância disso.
A próxima etapa consiste em inicializar o XMLDocument para pesquisar usando o XPath. Como o XML usa o esquema XAML como um namespace para alguns dos elementos (prefixados com um x, como x:Name), você precisará definir um namespace para todos os elementos na página, até mesmo aqueles não prefixados. Por exemplo, você não pode pesquisar nós correspondentes a XPath //TextBlock, mas pode especificar o namespace padrão para ter um novo prefixo (nesse caso, d de "dummy"), e pesquisar os nós padrão usando esse prefixo. Assim, //d:TextBlock funcionará. Eis o código:
NameTable myn = new NameTable();
XmlNamespaceManager mng = new XmlNamespaceManager(new NameTable());
mng.AddNamespace(“d”,
    “http://schemas.microsoft.com/winfx/2006/xaml/presentation”);
mng.AddNamespace(“x”, “http://schemas.microsoft.com/winfx/2006/xaml”);
Agora que você pode usar o XPath, localizar o nó que contém o nome da cidade e alterar sua propriedade Text para que seja o nome da cidade que o serviço identificou pelo CEP.
XmlNode xNode = xmlDoc.SelectSingleNode(
    “//d:TextBlock[@x:Name=’lblTownName’]”, mng);

xNode.Attributes[“Text”].Value = 
    myForecast.PlaceName + “,” + myForecast.StateCode;
Da mesma forma, você pode efetuar um loop pelos próximos três dias, localizar os nós de espaço reservado que contêm os locais desejados para seus valores e remover os valores corretos para o XML com o código mostrado na Figura 10.
string strXPath = “”;
string strDate = “”;
string strHigh = “”;
string strLow = “”;
string strWeatherURL = “”;

for (int n = 1; n <= 3; n++)
{
  strXPath = “//d:TextBlock[@x:Name=’lblDate” + n.ToString() + “’]”;
  xNode = xmlDoc.SelectSingleNode(strXPath, mng);
  strDate = myResults[n - 1].Day;
  xNode.Attributes[“Text”].Value = strDate;

  strXPath = “//d:TextBlock[@x:Name=’lblHigh” + n.ToString() + “’]”;
  xNode = xmlDoc.SelectSingleNode(strXPath, mng);
  strHigh = myResults[n - 1].MaxTemperatureF;
  xNode.Attributes[“Text”].Value = strHigh;

  strXPath = “//d:TextBlock[@x:Name=’lblLow” + n.ToString() + “’]”;
  xNode = xmlDoc.SelectSingleNode(strXPath, mng);
  strLow = myResults[n - 1].MinTemperatureF;
  xNode.Attributes[“Text”].Value = strLow;

  strXPath = “//d:Image[@x:Name=’imgWeather” + n.ToString() + “’]”;
  xNode = xmlDoc.SelectSingleNode(strXPath, mng);
  strWeatherURL = myResults[n - 1].WeatherImage;
  xNode.Attributes[“Source”].Value = strWeatherURL;
}
Agora que você já preencheu totalmente seu documento XML com o modelo e os dados corretos, a última etapa consiste em retorná-lo ao chamador. Você faz isso definindo o tipo de MIME e gravando o conteúdo do objeto XMLDocument diretamente no fluxo de resposta, desta forma:
Response.ContentType = “text/xml”;
Response.Write(xmlDoc.InnerXml);
Em seguida, remova o HTML de espaço reservado que o Visual Studio colocou na sua página ASPX. Remova tudo exceto a primeira linha do arquivo ASPX. Ao terminar, deve ter uma aparência semelhante ao código a seguir:
<%@ Page Language=”C#” AutoEventWireup=”true”    
         CodeFile=”XamlSource.aspx.cs” Inherits=”_Default” %>
A etapa final consiste em adicionar um novo arquivo XML à sua solução e chamá-lo de Scene.xaml. Você já viu uma referência anterior a esse arquivo no código. Cole o XAML meteorológico completo nesse arquivo. Agora você pode executar a página e deve ver o XAML retornado pela página XAMLSource.aspx no seu navegador.

Entregando o XAML ao Silverlight front-end
Nas etapas anteriores, você criou o modelo de XAML e depois um formulário da Web que usa esse XAML, consome um Web Service e coloca os resultados da chamada ao Web Service no XAML no local correto. A próxima etapa consiste em atender a uma página que contém o controle do Silverlight e o aponta para esse serviço XAML.
Abra o site da Web que você usou nas seções anteriores e adicione um novo formulário da Web denominado Default.aspx. Modifique o código HTML em Default.aspx para que se pareça com a Figura 11.
<%@ Page Language=”C#” AutoEventWireup=”true”
    CodeFile=”Default.aspx.cs” Inherits=”_Default” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
 “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
    <title>Weather</title>
    <meta http-equiv=’Content-Type’ 
          content=”text/html; charset=windows-1252”/>
    <script type=”text/javascript” src=”js/silverlight.js”></script>
</head>
<body>
<div id=”AgControl1Host” style=”background:#FFFFFF”>     
    <script type=”text/javascript”>
        Sys.Silverlight.createObjectEx(
            {source: ‘WeatherSite/XamlSource.aspx?ZIP=<%
                        if (Request.Params[“ZIP”] == null)
                            Response.Write(“98052”);
                        else
                           Response.Write(Request.Params[“ZIP”]);
              %>’, parentElement:’AgControl1Host’, Id:’AgControl1’, 
              properties:{width:’1024’, height:’530’, 
                  background:’white’, isWindowless:’false’, 
                  framerate:’24’, version:’0.8.5’}, 
              events:{onError:null, onLoad:null, onNotInstalled:null},
                  context:null});
    </script>
</div>
</body>
</html>
A parte importante disso está na chamada para Silverlight.createObjectEx, onde o videoplayer.xaml estático foi substituído por uma chamada para o aplicativo de origem XAML, passando-lhe o parâmetro que essa página Default.aspx recebeu para o CEP:
“WeatherSite/XamlSource.aspx?ZIP=<%
    if (Request.Params[“ZIP”] == null)
        Response.Write(“98052”);
    else
        Response.Write(Request.Params[“ZIP”]);
%>” 
Isso leva o parâmetro da solicitação para a página e o acrescenta a uma URL, que chamará a página XamlSource, criada por você na última etapa. A seguir, será feita uma chamada para XamlSource, passando o CEP e obtendo de volta um documento XAML, que será então processado pelo Silverlight. Os resultados da execução de Default.aspx?ZIP=90210 podem ser vistos na Figura 8.

Resumo
Neste artigo, você obteve uma introdução aprofundada ao Silverlight. Viu também alguns aplicativos que vão além do simples "Hello, World"; por exemplo, como o XAML é usado para construir interfaces do usuário, como pode ser vinculado ao JavaScript para gerar interatividade e como você pode ir além de um puro paradigma de cliente, passando a um paradigma baseado em servidor e tornando seus aplicativos mais flexíveis. Usando essa metodologia, você viu como criar um player de vídeo simples, que aceita o URI de um fluxo de vídeo e o reproduz, tornando-se ideal para uso em cenários como blogs.
Além disso, você aprendeu como criar um aplicativo com reconhecimento de dados, na forma de um monitor meteorológico com um modelo muito simples de distribuição para o cliente. Você simplesmente fez com que o componente do Silverlight chamasse o servidor para obter o XAML correto e processá-lo, formando um cliente fino avançado.
Embora o ASP.NET e a pilha da Microsoft representem uma plataforma bastante produtiva para a criação de aplicativos Web desse tipo, o download para esse artigo contém também uma versão Java do aplicativo. Essa versão oferece a mesma funcionalidade da ASP.NET: consumir o Web Service para obter os dados e depois carregar o XAML em um DOM de documento XML. Ela busca os nós adequados para os dados do modelo e substitui seus valores por aqueles do Web Service, antes de gravar o XAML concluído como um URI. O JSP (não listado) é então construído para fazer referência à URL desse servlet, a fim de processar o XAML usando o Silverlight.
É apenas o começo da adoção do Silverlight na Web. Com a sofisticação de um mecanismo de processamento XAML e a flexibilidade de usar tecnologias padrão de desenvolvimento na Web, vale a pena adicionar o Silverlight à sua caixa de ferramentas de desenvolvimento. Para obter mais informações, visite o Silverlight Developer Center no MSDN.

Laurence Moroney é um divulgador da tecnologia Silverlight na Microsoft. Ele é autor de nove livros de informática e mais de 100 artigos sobre tecnologia, inclusive "Programming Web.NEXT" (Programando Web.NEXT), que será lançado em breve pela Microsoft Press. Quando não está escrevendo artigos ou códigos, geralmente se dedica a enlouquecer a equipe de produtos com perguntas sobre o suporte a recursos no Silverlight.

Page view tracker