Palestra 25/09 e 26/09 - Academia de Ensino Superior - Sorocaba

By rdorta at agosto 27, 2010 10:56
Filed Under: Silverlight, Palestras

Nos dias 25/09 e 26/09 realizei 2 palestras na Academia de Ensino Superior em Sorocaba.

Convidado pelo Professor Sérgio Júnior, realizei as palestras sobre RIA e Realidade Aumentada para turmas de Sistemas de Informação.

Muito legal ver os alunos da faculdade criando projetos já visualizando a introdução de Realidade Aumentada no âmbito de negócios.

Obrigado aos alunos pela paciência e pelas excelentes perguntas e conversas realizadas durante as palestras.

Abaixo o PPT que utilizei.

 

Palestra AES - RIA.pptx (2,35 mb)

Silverlight 4 Dica do do Dia #8 Criando um CRUD com MVVM e Silverlight Parte 1 – Retrieve

By rdorta at julho 10, 2010 10:55
Filed Under: Arquitetura, Silverlight, MVVM

Olá,

Uma das coisas que sempre tenho dito em palestras e artigos é que um dos maiores potenciais do Silverlight, se não o maior, é a contrução de aplicações LOB(Line-of-business).

Aplicações deste tipo são aplicações que podem chegar a um grande nível de complexidade dependendo das regras de negócio da empresa que está precisando da aplicação.

Após grandes apelos da comunidade, o Silverlight 4 agora tem suporte a comandos. Isso facilita e muito a implementação de MVVM.

Pensando  nisso e atendendo a alguns pedidos de clientes e amigos, vou criar aqui um exemplo sobre como construir um CRUD simples com Silverlight utilizando o padrão de arquitetura MVVM.

Para iniciar, leiam o post que escrevi sobre MVVM para entender um pouco melhor este padrão.

Em nosso exemplo vamos usar a famosa base Northwind, para gerar as operações de CRUD(Create,Retrieve,Update, Delete). Vamos criar um WCF RIA SERVICE baseado em um modelo criado com Entity Framework.

Montando a Solução

Agora no Visual Studio vamos criar um novo projeto com o template Silverlight Businnes Application

image

Em nosso projeto Silverlight, vamos criar 3 novas pastas, uma para nossas ViewModel,outra para nossos Command e outra para nossas Interfaces.(eu gosto de organizar assim, mas fica a gosto de vocês)

image

Criando a Model de Dados

Agora vamos criar nosso modelo de dados e o serviço que irá recuperar estes dados.

Para manter o exemplo simples, vamos utilizar apenas a tabela Product da base Northwind.

No projeto Web, na pasta Models, clique com o botão direito depois em Add –> New File.

Na aba Data selecione ADO.Net Entity Data Model.

image

No Wizard de criação do EF, selecione Generate from Database e crie/escolha sua conexão com a base Northwind

image

Selecione a tabela de Produto e clique em Finalizar

image

Temos agora nossa Model de Produtos

image

Agora, vamos criar o serviço que expõe os dados dessa model.

NESTE PONTO VOCÊ DEVE COMPILAR SUA APLICAÇÃO PARA QUE NOSSO SERVIÇO ENXERGUE NOSSA MODEL.

Novamente no projeto Web, clique com o botão direito na pasta Services e adicione um novo Domain Service Class

image

No wizard de criação do serviço clique selecione a nossa model de produtos e habilite a edição

image

 

 

 

 

 

 

 

 

Agora temos a nossa classe de serviço:

   1:  
   2: namespace BlogSLMVVM.Web.Services
   3: {
   4:     using System;
   5:     using System.Collections.Generic;
   6:     using System.ComponentModel;
   7:     using System.ComponentModel.DataAnnotations;
   8:     using System.Data;
   9:     using System.Linq;
  10:     using System.ServiceModel.DomainServices.EntityFramework;
  11:     using System.ServiceModel.DomainServices.Hosting;
  12:     using System.ServiceModel.DomainServices.Server;
  13:     using BlogSLMVVM.Web.Models;
  14:  
  15:  
  16:     // Implements application logic using the NorthwindEntities context.
  17:     // TODO: Add your application logic to these methods or in additional methods.
  18:     // TODO: Wire up authentication (Windows/ASP.NET Forms) and uncomment the following to disable anonymous access
  19:     // Also consider adding roles to restrict access as appropriate.
  20:     // [RequiresAuthentication]
  21:     [EnableClientAccess()]
  22:     public class NorthwindService : LinqToEntitiesDomainService<NorthwindEntities>
  23:     {
  24:  
  25:         // TODO:
  26:         // Consider constraining the results of your query method.  If you need additional input you can
  27:         // add parameters to this method or create additional query methods with different names.
  28:         // To support paging you will need to add ordering to the 'Products' query.
  29:         public IQueryable<Product> GetProducts()
  30:         {
  31:             return this.ObjectContext.Products;
  32:         }
  33:  
  34:         public void InsertProduct(Product product)
  35:         {
  36:             if ((product.EntityState != EntityState.Detached))
  37:             {
  38:                 this.ObjectContext.ObjectStateManager.ChangeObjectState(product, EntityState.Added);
  39:             }
  40:             else
  41:             {
  42:                 this.ObjectContext.Products.AddObject(product);
  43:             }
  44:         }
  45:  
  46:         public void UpdateProduct(Product currentProduct)
  47:         {
  48:             this.ObjectContext.Products.AttachAsModified(currentProduct, this.ChangeSet.GetOriginal(currentProduct));
  49:         }
  50:  
  51:         public void DeleteProduct(Product product)
  52:         {
  53:             if ((product.EntityState == EntityState.Detached))
  54:             {
  55:                 this.ObjectContext.Products.Attach(product);
  56:             }
  57:             this.ObjectContext.Products.DeleteObject(product);
  58:         }
  59:     }
  60: }
  61:  
  62:  

MVVM RLZ – cRud - Retrieve

Agora vamos ao core do negócio, criar as VielModel e os Comandos.

Vamos começar pela interface.

No projeto Silverlight na pasta Views, adicone uma nova Silverlight Page chamada ProductsView.

Compile e abra o projeto no Expression Blend 4 e abra a ProductsView.xaml.

Adicione 3 botões (Novo,Editar e Excluir), 1 BusyIndicator e 1 DataGrid em sua page.

Adicione a seguinte expressão a propriedade ItemsSource da Datagrid : {Binding AllProducts}

Adicione a seguinte expressão a propriedade IsBusy do BusyIndicato : {Binding IsLoading}

image

Eis o XAML

   1: <navigation:Page 
   2:            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   4:            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   5:            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   6:            xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
   7:            xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" x:Class="BlogSLMVVM.Views.ProductsView"
   8:            mc:Ignorable="d"
   9:            d:DesignWidth="640" d:DesignHeight="480"
  10:            Title="ProductsView Page">
  11:     <Grid x:Name="LayoutRoot">
  12:  
  13:         <sdk:DataGrid x:Name="dtgDados" Margin="43,149,48,22" ItemsSource="{Binding AllProducts}"/>
  14:  
  15:         <toolkit:BusyIndicator x:Name="bsiCarregando" Content="BusyIndicator" Height="32" Margin="52,108,71,0" VerticalAlignment="Top" IsBusy="{Binding IsLoading}"/>
  16:         <Button x:Name="btnNovo" Content="Novo" HorizontalAlignment="Left" Height="27" Margin="52,64,0,0" VerticalAlignment="Top" Width="97"/>
  17:         <Button x:Name="btnEditar" Content="Editar" HorizontalAlignment="Left" Height="27" Margin="165,64,0,0" VerticalAlignment="Top" Width="97"/>
  18:         <Button x:Name="btnExcluir" Content="Excluir" Height="27" Margin="275,64,268,0" VerticalAlignment="Top"/>
  19:  
  20:     </Grid>
  21: </navigation:Page>

Vamos criar o link para nossa nova página.

Abra o arquivo MainPage.xaml, localize o StackPanel chamado LinksStackPanel e adicione um divisor e um link para nossa página:

   1: <Rectangle x:Name="Divider1_Copy" Style="{StaticResource DividerStyle}"/>
   2:             <HyperlinkButton x:Name="Link2_Copy" Style="{StaticResource LinkStyle}" 
   3:                 NavigateUri="/ProductsView" TargetName="ContentFrame" Content="Products"/>

Agora vamos criar nossa ViewModel.

No projeto Silverlight, na pasta ViewModel adicione uma nova classe com o nome ProductsViewModel

Abaixo segue o código final da classe, vou comentar os pontos principais mais abaixo.

   1: using System;
   2: using System.Net;
   3: using System.Windows;
   4: using System.Windows.Controls;
   5: using System.Windows.Documents;
   6: using System.Windows.Ink;
   7: using System.Windows.Input;
   8: using System.Windows.Media;
   9: using System.Windows.Media.Animation;
  10: using System.Windows.Shapes;
  11: using System.ComponentModel;
  12: using BlogSLMVVM.Web.Services;
  13: using BlogSLMVVM.Web.Models;
  14: using System.Linq;
  15: using System.ServiceModel.DomainServices.Client;
  16:  
  17: namespace BlogSLMVVM.ViewModel
  18: {
  19:     public class ProductsViewModel : INotifyPropertyChanged
  20:     {
  21:  
  22:         #region Propriedades Privadas
  23:         private NorthwindContext gctxNorthwind = null;
  24:         private bool gIsLoading = false;
  25:         #endregion
  26:  
  27:         #region Propriedades Públicas
  28:         /// <summary>
  29:         ///     Indica se o serviço está ocupado recuperando a listagem
  30:         /// </summary>
  31:         public bool IsLoading
  32:         {
  33:             get { return gIsLoading; }
  34:             set { gIsLoading = value; }
  35:         }
  36:  
  37:         /// <summary>
  38:         ///     Retorna a lista de todos os produtos
  39:         /// </summary>
  40:         public EntitySet<Product> AllProducts
  41:         {
  42:             get { return GetAllProducts(); }
  43:         }
  44:         #endregion
  45:  
  46:         #region Construtor
  47:         public ProductsViewModel()
  48:         {
  49:             gIsLoading = true;
  50:             this.gctxNorthwind = new NorthwindContext();
  51:             this.gctxNorthwind.Load<Product>(
  52:                                this.gctxNorthwind.GetProductsQuery(),
  53:                                delegate(LoadOperation<Product> loadOperation)
  54:                                {
  55:                                    this.IsLoading = false;
  56:                                    RaisePropertyChanged("IsLoading");
  57:                                }, null);
  58:         }
  59:         #endregion
  60:  
  61:         #region Chamadas do Serviço
  62:         /// <summary>
  63:         ///     Chamada para os produtos
  64:         /// </summary>
  65:         /// <returns></returns>
  66:         private EntitySet<Product> GetAllProducts()
  67:         {
  68:             return this.gctxNorthwind.Products;
  69:         }
  70:         #endregion
  71:  
  72:  
  73:         #region INotifyPropertyChanged Members
  74:  
  75:         public event PropertyChangedEventHandler PropertyChanged;
  76:  
  77:         private void RaisePropertyChanged(string propertyname)
  78:         {
  79:             if (PropertyChanged != null)
  80:             {
  81:                 PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
  82:             }
  83:         }
  84:  
  85:         #endregion
  86:     }
  87: }

A primeira coisa é reparar que a classe está implementando a interface INotifyPropertyChanged. Estamos fazendo isso para que a view entenda que houve uma alteração e que ela deve se atualizar.

Em nosso construtor, estamos inicializando o serviço que criamos anteriormente e carregando os Produtos, note que estamos utilizando a propriedade IsLoading para manter a view informada de que o serviço está em execução.

Por fim temos a propriedade AllProducts que retorna a lista de produtos carregada pelo serviço.

Agora vamos ao código da nossa view:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Net;
   5: using System.Windows;
   6: using System.Windows.Controls;
   7: using System.Windows.Documents;
   8: using System.Windows.Input;
   9: using System.Windows.Media;
  10: using System.Windows.Media.Animation;
  11: using System.Windows.Shapes;
  12: using System.Windows.Navigation;
  13: using BlogSLMVVM.ViewModel;
  14:  
  15: namespace BlogSLMVVM.Views
  16: {
  17:     public partial class ProductsView : Page
  18:     {
  19:  
  20:         private ProductsViewModel vmdProduto = null;
  21:  
  22:         public ProductsView()
  23:         {
  24:             InitializeComponent();
  25:             this.vmdProduto = new ProductsViewModel();
  26:             this.DataContext = this.vmdProduto;
  27:         }
  28:  
  29:         // Executes when the user navigates to this page.
  30:         protected override void OnNavigatedTo(NavigationEventArgs e)
  31:         {
  32:         }
  33:  
  34:     }
  35: }

Bem simples, apenas instanciamos a nossa ViewModel e a indicamos como contexto da View.

Pronto!!!

Já estamos com a nossa listagem :)

image 

Eis o fonte utilizado até aqui:

BlogSLMVVM - Parte 1.zip (4,77 mb)

Em breve o próximo post com introdução aos Commands, as outras letras do CRUD e o código fonte final :)

Silverlight 4 Dica do do Dia #8 Criando um CRUD com MVVM e Silverlight Parte 2 – Commands e Insert/Update/Delete

 

Silverlight 4 Dica do Dia #7 – Pivot Viewer Basics

By rdorta at julho 01, 2010 18:08
Filed Under: Silverlight

Após mais uma excelente twitada e blogada do Rene de Paula – User Experience Evangelist da Microsoft, conferi o lançamento do Pivot Viewer.

O assunto é bem extenso, vou criar uma série de posts em breve para detalhar um pouco melhor o controle. Neste post vou apenas mostar o que consegui fazer em algumas horas com alguns conhecimentos que eu já tinha.

Inicialmente alguns testes e esse exemplo básico abaixo, buscando as pessoas que você segue em seu twitter :p Os code snippets estão abaixo assim como o fonte.

De início vocês irão ver que eu estou seguindo no Twitter, mas caso queiram, é só digitar o usuário de vocês e aguardar ele gerar o Deep Zoom(pode demorar um pouco dependendo de quantas pessoas você segue)

Get Microsoft Silverlight

 

O Pivot Viewer é um controle que permite ao desenvolvedor disponibilizar GRANDES (mas grandes MESMO) quantidades de informações de uma só vez e também visualizar a conexão entre elas.

O controle Pivot exibe “coleções” de informações, utilizando DEEP ZOOM em sua máxima performance.

Mais informações sobre o Pivot Viewer você encontra em:

http://www.getpivot.com/

E para baixar as assemblys vá em http://www.getpivot.com/download/

Vamos criar um exemplo de Pivot Viewer com essas assemblys.

Outro SDK que vamos utilizar neste exemplo é o http://linqtotwitter.codeplex.com/

Este é um excelente SDK para comunicação com o Twitter. Não pretendo me alongar demais sobre o Deep Zoom Dinamico e o LINQ to Twitter neste post. Talvez em outro post caso queriam, me peçam no Twitter

Enfim, vamos começar.

Após baixar e instalar o Pivot, as assemblys vão estar disponíveis no diretório de SDKS da Microsoft, no meu caso (Windows 7 x64) estão em:

C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\PivotViewer\Jun10\Bin

image

Vamos criar um projeto Silverlight com um Pivot Viewer que leia uma coleção básica. Nos próximos posts vamos melhorar um pouco a aplicação colocando alguns filtros mais legais. (Deem sugestões de filtros de Twitter para nossa aplicação no Twitter)

image

Adicione as referências do Pivot Viewer no seu projeto Silverlight:

image

Vamos adicionar o controle Pivot em nosso XAML. E também um textbox para obter o id do twitter de nosso usuário e um TextBlock para informar que o serviço de DeepZoom está sendo executado.

   1: <UserControl x:Class="SLPivotViewer.MainPage"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   5:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   6:     mc:Ignorable="d"
   7:     xmlns:local="clr-namespace:System.Windows.Pivot;assembly=System.Windows.Pivot"
   8:     d:DesignHeight="300" d:DesignWidth="400">
   9:  
  10:     <Grid x:Name="LayoutRoot" Background="White" >
r: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">  11:  
  12:         <Grid Grid.Row="0" Grid.Column="0">
  13:             <StackPanel Orientation="Horizontal"  Height="30" VerticalAlignment="Top">
  14:                 <TextBlock Text="Digite o seu usuário do twitter:"></TextBlock>
  15:                 <TextBox x:Name="txtUser" Width="200"></TextBox>
  16:                 <Button x:Name="btnBuscar" Content="Buscar" Click="btnBuscar_Click"></Button>
  17:             </StackPanel>
  18:             <TextBlock x:Name="txbAguarde" Text="Aguarde, o DeepZoom de amigos está sendo gerado" Height="18" Visibility="Collapsed" VerticalAlignment="Top" Margin="0,34,0,0"/>
  19:         </Grid>
  20:         <Grid Grid.Column="0" Margin="0,65,0,0" d:LayoutOverrides="GridBox">
  21:            <local:PivotViewer x:Name="pvtViewer"></local:PivotViewer>
  22:         </Grid>
  23:  
  24:     </Grid>
  25: </UserControl>

 

Antes de mais nada é interessante que você leia o post que fiz ano passado sobre como criar coleções DEEP ZOOM Dinamicamente:

Deep Zoom Dinamico

Agora em nosso projeto Web, vamos adicionar um serviço Domain Service que irá gerar as imagens do DeepZoom caso as mesmas não existam, aqui vamos usar o Linq to Twitter e o Deep Zoom Dinamico

   1:  
   2: namespace SLPivotViewer.Web.Services
   3: {
   4:     using System;
   5:     using System.Collections.Generic;
   6:     using System.ComponentModel;
   7:     using System.ComponentModel.DataAnnotations;
   8:     using System.Linq;
   9:     using System.ServiceModel.DomainServices.Hosting;
  10:     using System.ServiceModel.DomainServices.Server;
  11:     using LinqToTwitter;
  12:     using System.IO;
  13:     using System.Web;
  14:     using System.Xml.Linq;
  15:     using Microsoft.DeepZoomTools;
  16:     using System.Security.Principal;
  17:     using System.Net;
  18:  
  19:     [EnableClientAccess()]
  20:     public class TwitterService : DomainService
  21:     {
  22:  
  23:         [Invoke]
  24:         public void GenerateUsersCollection(string pstrUserName)
  25:         {
  26:             //LOGANDO OS PASSOS
  27:             StreamWriter writer = new StreamWriter(HttpContext.Current.Server.MapPath("~/log.txt"));
  28:             try
  29:             {
  30:                 //GARANTINDO A EXISTENCIA DOS DIRETORIOS
  31:                 if (!File.Exists(HttpContext.Current.Server.MapPath("~/Collections/" + pstrUserName + ".cxml")))
  32:                 {
  33:                     writer.Write("INICIO - CRIAR DIRETORIOS");
  34:                     if (!Directory.Exists(HttpContext.Current.Server.MapPath("~/Collections/")))
  35:                     {
  36:                         Directory.CreateDirectory(HttpContext.Current.Server.MapPath("~/Collections/"));
  37:                     }
  38:  
  39:                     if (!Directory.Exists(HttpContext.Current.Server.MapPath("~/imgs/")))
  40:                     {
  41:                         Directory.CreateDirectory(HttpContext.Current.Server.MapPath("~/imgs/"));
  42:                     }
  43:  
  44:                     if (!Directory.Exists(HttpContext.Current.Server.MapPath("~/Collections/")))
  45:                     {
  46:                         Directory.CreateDirectory(HttpContext.Current.Server.MapPath("~/Collections/"));
  47:                     }
  48:  
  49:                     if (!Directory.Exists(HttpContext.Current.Server.MapPath("~/ClientBin/")))
  50:                     {
  51:                         Directory.CreateDirectory(HttpContext.Current.Server.MapPath("~/ClientBin/"));
  52:                     }
  53:  
  54:                     if (!Directory.Exists(HttpContext.Current.Server.MapPath("~/ClientBin/" + pstrUserName + "/")))
  55:                     {
  56:                         Directory.CreateDirectory(HttpContext.Current.Server.MapPath("~/ClientBin/" + pstrUserName + "/"));
  57:                     }
  58:  
  59:                     if (!Directory.Exists(HttpContext.Current.Server.MapPath("~/ClientBin/" + pstrUserName + "/GeneratedImages/")))
  60:                     {
  61:                         Directory.CreateDirectory(HttpContext.Current.Server.MapPath("~/ClientBin/" + pstrUserName + "/GeneratedImages/"));
  62:                     }
  63:  
  64:                     if (!Directory.Exists(HttpContext.Current.Server.MapPath("~/ClientBin/" + pstrUserName + "/GeneratedImages/output_images/")))
  65:                     {
  66:                         Directory.CreateDirectory(HttpContext.Current.Server.MapPath("~/ClientBin/" + pstrUserName + "/GeneratedImages/output_images/"));
  67:                     }
  68:  
  69:  
  70:                     writer.Write("FIM - CRIAR DIRETORIOS");
  71:  
  72:                     writer.Write("INICIO - CONEXAO TWITTER");
  73:  
  74:                     //INICIANDO A CONSULTA A API DO TWITTER
  75:                     TwitterContext twitterCtx = new TwitterContext();
  76:                     //CARREGANDO OS USUARIOS QUE ESTÃO SENDO SEGUIDOS PELO USUARIO DA APLICAÇÃO
  77:                     var users =
  78:                         from tweet in twitterCtx.User
  79:                         where tweet.Type == UserType.Friends &&
  80:                               tweet.ID == pstrUserName
  81:                         select tweet;
  82:  
  83:  
  84:                     writer.Write("FIM - CONEXAO TWITTER");
  85:                     //CRIAÇÃO DO DEEP ZOOM
  86:                     List<string> lstXMLs = new List<string>();
  87:  
  88:                     string strCaminhoImagensGeradas = HttpContext.Current.Server.MapPath("/Collections/" + pstrUserName + "/GeneratedImages/");
  89:  
  90:                     writer.Write("INICIO - CRIAR DEEP ZOOM");
  91:                     CollectionCreator cc = new CollectionCreator();
  92:  
  93:                     //CRIAÇÃO DO XML DA COLEÇÃO
  94:                     XDocument doc = new XDocument();
  95:                     XElement elCollection = new XElement("Collection");
  96:                     XElement elFacetCateogies = new XElement("FacetCategories");
  97:                     XElement facet = new XElement("FacetCategory");
  98:                     XElement elItems = new XElement("Items");
  99:                     XAttribute at = new XAttribute("Name", "Teste");
 100:                     XAttribute at2 = new XAttribute("Type", "String");
 101:                     facet.Add(at);
 102:                     facet.Add(at2);
 103:                     elFacetCateogies.Add(facet);
 104:                     elCollection.Add(elFacetCateogies);
 105:  
 106:                     //ADICIONANDO OS NÓS DAS IMAGENS
 107:                     int intContador = 0;
 108:                     foreach (User objUser in users)
 109:                     {
 110:                         XElement elItem = new XElement("Item");
 111:                         writer.Write("    INICIO - CRIAR IMAGEM");
 112:                         ImageCreator ic = new ImageCreator();
 113:                         ic.TileSize = 256;
 114:                         ic.TileFormat = ImageFormat.AutoSelect;
 115:                         ic.ImageQuality = 1;
 116:                         string target = strCaminhoImagensGeradas + "output_images\\" + intContador;
 117:  
 118:                         if (!File.Exists(HttpContext.Current.Server.MapPath("~/imgs/" + objUser.Identifier.ScreenName + ".jpg")))
 119:                         {
 120:                             WebClient client = new WebClient();
 121:                             client.DownloadFile(objUser.ProfileImageUrl, HttpContext.Current.Server.MapPath("~/imgs/" + objUser.Identifier.ScreenName + ".jpg"));
 122:                         }
 123:  
 124:                         ic.Create(HttpContext.Current.Server.MapPath("~/imgs/" + objUser.Identifier.ScreenName + ".jpg"), target);
 125:                         writer.Write("    FIM - CRIAR IMAGEM");
 126:                         lstXMLs.Add(Path.ChangeExtension(target, ".xml"));
 127:                         elItem.Add(new XAttribute("Img", "#" + intContador.ToString()));
 128:                         elItem.Add(new XAttribute("Id", intContador.ToString()));
 129:                         elItem.Add(new XAttribute("Href", "http://www.twitter.com/" + objUser.Identifier.ScreenName));
 130:                         elItem.Add(new XAttribute("Name", objUser.Name));
 131:                         elItems.Add(elItem);
 132:                         intContador++;
 133:                     }
 134:  
 135:                     cc.TileSize = 256;
 136:  
 137:                     cc.TileFormat = ImageFormat.Jpg;
 138:  
 139:                     cc.MaxLevel = 8;
 140:  
 141:                     cc.ImageQuality = 1;
 142:  
 143:                     cc.Create(lstXMLs, strCaminhoImagensGeradas + "output");
 144:                     writer.Write("FIM - CRIAR DEEPZOOM");
 145:                     elItems.Add(new XAttribute("ImgBase", pstrUserName + @"\GeneratedImages\output.xml"));
 146:                     elCollection.Add(elItems);
 147:                     doc.Add(elCollection);
 148:                     string strFinal = doc.ToString();
 149:                     strFinal = strFinal.Replace("<Collection>", "<Collection xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" SchemaVersion=\"1\" xmlns:d1p1=\"http://schemas.microsoft.com/livelabs/pivot/collection/2009\" xmlns=\"http://schemas.microsoft.com/collection/metadata/2009\">");
 150:                     StreamWriter final = new StreamWriter(HttpContext.Current.Server.MapPath("~/Collections/" + pstrUserName + ".cxml"));
 151:                     final.Write(strFinal);
 152:                     final.Close();
 153:                 }
 154:             }
 155:             catch (Exception ex)
 156:             {
 157:                 writer.Write(ex.Message);
 158:             }
 159:             finally
 160:             {
 161:                 writer.Close();
 162:             }
 163:         }
 164:  
 165:  
 166:     }
 167: }
 168:  
 169:  

 

 

O código está bem comentado, mas basicamente o que fiz foi utilizar o meu artigo de Deep Zoom Dinamico e os exemplos básicos do LINQ To Twitter.

 

Por fim, basta apenas chamar o serviço e passar a coleção para o Pivot Viewer

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Net;
   5: using System.Windows;
   6: using System.Windows.Controls;
   7: using System.Windows.Documents;
   8: using System.Windows.Input;
   9: using System.Windows.Media;
  10: using System.Windows.Media.Animation;
  11: using System.Windows.Shapes;
  12: using SLPivotViewer.Web.Services;
  13: using System.ServiceModel.DomainServices.Client;
  14: using System.Windows.Pivot;
  15:  
  16: namespace SLPivotViewer
  17: {
  18:     public partial class MainPage : UserControl
  19:     {
  20:         public MainPage()
  21:         {
  22:             InitializeComponent();
  23:             //Carregando a coleção do Dorta
  24:             this.pvtViewer.LoadCollection("http://localhost:19227//Collections/dortaway.cxml", string.Empty);
  25:         }
  26:  
  27:         InvokeOperation opeListagem = null;
  28:         void btnBuscar_Click(object sender, RoutedEventArgs e)
  29:         {
  30:             //Instanciando o serviço que irá gerar o coleção
  31:             TwitterContext ctx = new TwitterContext();
  32:             //executando o método
  33:             opeListagem = ctx.GenerateUsersCollection(this.txtUser.Text);
  34:             //atribuindo o método que será disparado quando o serviço completar
  35:             opeListagem.Completed += opeListagem_Completed;
  36:             //avisando o usuário que o serviço está em execução
  37:             txbAguarde.Visibility = System.Windows.Visibility.Visible;
  38:         }
  39:  
  40:         void pvtViewer_CollectionLoadingFailed(object sender, CollectionErrorEventArgs e)
  41:         {
  42:             //em caso de erro vamos avisar o usuário
  43:             MessageBox.Show(e.Exception.Message);
  44:         }
  45:  
  46:         void opeListagem_Completed(object sender, EventArgs e)
  47:         {
  48:             if (opeListagem.HasError)
  49:             {
  50:                 //em caso de erro vamos avisar o usuário
  51:                 MessageBox.Show(opeListagem.Error.Message);
  52:                 opeListagem.MarkErrorAsHandled();
  53:             }
  54:             else
  55:             {
  56:                 //vamos carregar a coleção
  57:                 txbAguarde.Visibility = System.Windows.Visibility.Collapsed;
  58:                 this.pvtViewer.LoadCollection("http://localhost:19227/Collections/" + this.txtUser.Text + ".cxml", string.Empty);
  59:                 this.pvtViewer.CollectionLoadingFailed += new EventHandler<CollectionErrorEventArgs>(pvtViewer_CollectionLoadingFailed);
  60:             }
  61:             
  62:         }
  63:     }
  64: }

 

Abaixo segue o fonte que usei. Bom divertimento :)

SLPivotViewer.zip (13,83 mb)

[]´s

Silverlight 4 Dica do Dia #6 – Mapas do BING Maps no Silverlight

By rdorta at junho 25, 2010 15:46
Filed Under: Arquitetura, Silverlight

Olá,

Estive trabalhando em uma prova de conceito para um cliente da Makesys, que envolve a utilização de Bing Maps, e resolvi compartilhar com vocês como fazer para utilizar o controle de Mapas do Bing Maps.

Vamos criar uma aplicação que contenha o controle de mapas e que adicione Pins a medida que o usuário clica no mapa.

Para começar, acesse o site do Bing Maps destinado a Devs e de uma olhada em todas as opções, em nosso exemplo vamos utilizar o controle Silverlight e o SOAP Services:

http://www.microsoft.com/maps/developers/

Depois acesse o site portal do Bing Maps, para criar o seu token de desenvolvimento, você irá precisar do seu Windows Live Id:

https://www.bingmapsportal.com/

Baixe as assemblys do controle Silverlight aqui:

http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=beb29d27-6f0c-494f-b028-1e0e3187e830

Crie um projeto do tipo Silverlight Application, Conforme mostra a figura abaixo:

image

Gere a solução e adicione as referências para as dlls do Bing Maps que no meu caso (Windows 7 64 bits) se encontram em:

C:\Program Files (x86)\Bing Maps Silverlight Control\V1\Libraries

image

Agora clique no botão Salvar Tudo. E vamos para o Expression Blend 4. Abra sua solução.

Abra a MainPage.xaml e clique no botão de procura de controles, navegue até a dll Microsoft.Maps.MapControl.dll e você verá os controles abaixo:

image

Vamos utilizar o controle map. Selecione o mesmo e adicione em sua MainPage

image

 

 

 

De um nome ao controle e adicione um handler ao evento MouseClick:

image

(IMPORTANTE!!!!)Agora, adicione a chave de registro que você obteve no primeiro passo, ficará algo assim:

   1: <Microsoft_Maps_MapControl:Map CredentialsProvider="SEUTOKENDEAPLICACAOAQUI" x:Name="mapMapa" d:LayoutOverrides="Width, Height" MouseClick="mapMapa_MouseClick"/>

De volta ao Visual Studio, eis o código final comentado:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Net;
   5: using System.Windows;
   6: using System.Windows.Controls;
   7: using System.Windows.Documents;
   8: using System.Windows.Input;
   9: using System.Windows.Media;
  10: using System.Windows.Media.Animation;
  11: using System.Windows.Shapes;
  12: using Microsoft.Maps.MapControl;
  13:  
  14: namespace BlogBingMaps
  15: {
  16:     public partial class MainPage : UserControl
  17:     {
  18:         public MainPage()
  19:         {
  20:             InitializeComponent();
  21:         }
  22:  
  23:         private void mapMapa_MouseClick(object sender, Microsoft.Maps.MapControl.MapMouseEventArgs e)
  24:         {
  25:             //Criando o pin
  26:             Pushpin pspPin = new Pushpin();
  27:             //Obtendo a localização com latitude e longitude do ponto em que o usuário clicou
  28:             pspPin.Location = mapMapa.ViewportPointToLocation(e.ViewportPoint);
  29:             //Adicionando o pin ao mapa
  30:             mapMapa.Children.Add(pspPin);
  31:         }
  32:     }
  33: }

Perfeito!!!

Já temos uma aplicação em Silverlight com integração ao Bing Maps.

Para deixar a coisa mais interessante, vamos mostrar o endereço da Microsoft em SP como visualização inicial, utilizando o SOAP Service para obter o código geográfico(latitude e longitude) através do endereço:

Adicione um Service Reference ao seu projeto para o endereço:

http://dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc?wsdl

Vamos nomear o serviço como GeocodeService:

image

 

Adicone o import para o namespace do serviço:

   1: using BlogBingMaps.GeocodeService;

Abaixo segue o código completo comentado:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Net;
   5: using System.Windows;
   6: using System.Windows.Controls;
   7: using System.Windows.Documents;
   8: using System.Windows.Input;
   9: using System.Windows.Media;
  10: using System.Windows.Media.Animation;
  11: using System.Windows.Shapes;
  12: using Microsoft.Maps.MapControl;
  13: using Microsoft.Maps.MapControl.Core;
  14: using BlogBingMaps.GeocodeService;
  15:  
  16: namespace BlogBingMaps
  17: {
  18:     public partial class MainPage : UserControl
  19:     {
  20:         public MainPage()
  21:         {
  22:             InitializeComponent();
  23:  
  24:             //cria a instancia do serviço
  25:             GeocodeServiceClient cliServico = new GeocodeServiceClient();
  26:             //dimensiona a chave de desenvolvimento
  27:             string strChave = "SUA CHAVE AQUI";
  28:             //cria o objeto de request
  29:             GeocodeRequest reqGeoRequest = new GeocodeRequest();
  30:             // cria as credenciais
  31:             reqGeoRequest.Credentials = new Credentials();
  32:             reqGeoRequest.Credentials.ApplicationId = strChave;
  33:  
  34:             //endereço que queremos buscar
  35:             string strEndereco = "Av Das Nacoes Unidas, 12901, São Paulo";
  36:             reqGeoRequest.Query = strEndereco;
  37:  
  38:             //adicina handler para o completed
  39:             cliServico.GeocodeCompleted += new EventHandler<GeocodeCompletedEventArgs>(cliServico_GeocodeCompleted);
  40:             cliServico.GeocodeAsync(reqGeoRequest);
  41:         }
  42:  
  43:         void cliServico_GeocodeCompleted(object sender, GeocodeCompletedEventArgs e)
  44:         {
  45:             GeocodeResponse resResultado = e.Result;
  46:             //define a latitude, longitude e fator de zoom da visualização
  47:             mapMapa.SetView(new Location(resResultado.Results[0].Locations[0].Latitude, resResultado.Results[0].Locations[0].Longitude), 14);
  48:         }
  49:  
  50:         private void mapMapa_MouseClick(object sender, Microsoft.Maps.MapControl.MapMouseEventArgs e)
  51:         {
  52:             //Criando o pin
  53:             Pushpin pspPin = new Pushpin();
  54:             //Obtendo a localização com latitude e longitude do ponto em que o usuário clicou
  55:             pspPin.Location = mapMapa.ViewportPointToLocation(e.ViewportPoint);
  56:             //Adicionando o pin ao mapa
  57:             mapMapa.Children.Add(pspPin);
  58:         }
  59:     }
  60: }

Por fim, no arquivo ServiceReferences.config, remova o endpoint binaryhttp:

   1: <configuration>
   2:     <system.serviceModel>
   3:         <bindings>
   4:             <basicHttpBinding>
   5:                 <binding name="BasicHttpBinding_IGeocodeService" maxBufferSize="2147483647"
   6:                     maxReceivedMessageSize="2147483647">
   7:                     <security mode="None" />
   8:                 </binding>
   9:             </basicHttpBinding>
  10:             <customBinding>
  11:                 <binding name="CustomBinding_IGeocodeService">
  12:                     <binaryMessageEncoding />
  13:                     <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
  14:                 </binding>
  15:             </customBinding>
  16:         </bindings>
  17:         <client>
  18:             <endpoint address="http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc"
  19:                 binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IGeocodeService"
  20:                 contract="GeocodeService.IGeocodeService" name="BasicHttpBinding_IGeocodeService" />
  21:         </client>
  22:     </system.serviceModel>
  23: </configuration>

 

Espero que gostem, abaixo o silvelright final e o fonte :)

 

Até a próxima

BlogBingMaps.zip (661,48 kb)

Silverlight 4 Dica do Dia #5 - Realidade Aumentada – YES WE CAN!!!

By rdorta at junho 21, 2010 16:43
Filed Under: Arquitetura, Silverlight

Após meu último post, sobre integração com WebCam recebi muitas perguntas referentes a Realidade Aumentada.

Portanto, resolvi escrever este post sobre o assunto como forma de iniciar as pessoas que querem aprender mais sobre o assunto.

Sugiro que quem ainda não leu meu último post, que comece por ele, porque neste post vou assumir que você já sabe como capturar as imagens vindas da sua WebCam.

Depois de ler o post anterior, imprima a imagem abaixo:

image

Essa imagem é a que vamos identificar dentro da nossa aplicação.

Bom, partindo do programa gerado no último post, temos uma aplicação que captura os dados da webcam e exibe na tela.

Vamos utilizar o SLARToolkit, como nosso framework de identificação de padrão de imagem e substituição.

Adicione as referências das 2 dlls do toolkit no projeto.

Agora baixe o arquivo Pattern que representa a imagem acima: http://blogs.makesys.com.br/dorta/makesys.pat. Adicione ela ao projeto, clique em cima dela, vá até a aba propriedades e troque a sua Build Action para Resource.

Adicione o pattern no projeto.

Agora, a partir do projeto que criamos no meu último post, vamos adicionar um canvas após o Rectangle que serviu como ViewPort, dentro deste canvas, vou adicionar uma imagem, mas pode ser adicionado qualquer outro objeto Silverlight, eis o XAML completo:

   1: <UserControl x:Class="SLRealidadeAumentada.MainPage"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   5:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   6:     mc:Ignorable="d"
   7:     d:DesignHeight="550" d:DesignWidth="700"
   8:     Loaded="UserControl_Loaded">
   9:  
  10:     <Grid x:Name="LayoutRoot" Background="White">
  11:         <StackPanel>
  12:             <Grid Width="640" Height="480">
  13:                 <Rectangle Name="Viewport" Stroke="Black" StrokeThickness="2" />
  14:                 <Canvas>
  15:                     <Grid Background="White" x:Name="imgMakesys" Visibility="Collapsed"  >
  16:                         <Image Source="logo_makesys.png" Height="91" Width="261"/>
  17:                     </Grid>
  18:                 </Canvas>
  19:             </Grid>
  20:             <Button Content="IniciarCaptura" HorizontalAlignment="Center" Click="Button_Click" />
  21:         </StackPanel>
  22:     </Grid>
  23: </UserControl>

Abaixo o código final:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Net;
   5: using System.Windows;
   6: using System.Windows.Controls;
   7: using System.Windows.Documents;
   8: using System.Windows.Input;
   9: using System.Windows.Media;
">  10: using System.Windows.Media.Animation;
  11: using System.Windows.Shapes;
  12: using SLARToolKit;
  13: using System.Windows.Media.Media3D;
  14:  
  15: namespace SLRealidadeAumentada
  16: {
  17:     public partial class MainPage : UserControl
  18:     {
  19:  
  20:         CaptureSource cpsVideo;
  21:         CaptureSourceMarkerDetector cmkDetectorPattern;
  22:  
  23:         public MainPage()
  24:         {
  25:             InitializeComponent();
  26:         }
  27:  
  28:         private void UserControl_Loaded(object sender, RoutedEventArgs e)
  29:         {
  30:             // Instancia o objeto que manipula a WebCam
  31:             cpsVideo = new CaptureSource();
  32:             // Define qual webcam será o alvo do objeto, no caso a câmera padrão do Sistema
  33:             cpsVideo.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
  34:  
  35:             //Cria o objeto que recebe os dados do video
  36:             var vbsVideo = new VideoBrush();
  37:             vbsVideo.SetSource(cpsVideo);
  38:             // Preenche o retangulo com os dados capturados do video
  39:             Viewport.Fill = vbsVideo;
  40:  
  41:             //  Initialize the o detector
  42:             cmkDetectorPattern = new CaptureSourceMarkerDetector();
  43:             // Carrega o pattern que deve ser procurado, ele tem 64 segmentos e 80 milimetros de 
  44:             var patPattern = Marker.LoadFromResource("makesys.pat", 64, 64, 80);
  45:             // Cria a parspectiva com planos de 1 a 4000
  46:             cmkDetectorPattern.Initialize(cpsVideo, 1, 4000, patPattern);
  47:  
  48:             // Vincula o handler de captura do pattern
  49:             // O evento é disparado se pelo menos um pattern é identificado na imagem
  50:             cmkDetectorPattern.MarkersDetected += (senderDelegate, eDelegate) =>
  51:             {
  52:                 // Cria uma nova tread para manipular a projeção do objeto que está no canvas
  53:                 Dispatcher.BeginInvoke(() =>
  54:                 {
  55:                     // Calcula a matrix de projeção
  56:                     var dreResultado = eDelegate.DetectionResults;
  57:                     if (dreResultado.HasResults)
  58:                     {
  59:                         // Centro do Objeto
  60:                         Matrix3D mtdCentro = Matrix3DFactory.CreateTranslation(-imgMakesys.ActualWidth * 0.5, -imgMakesys.ActualHeight * 0.5, 0);
  61:                         // Troca o eixo Y e diminui a escala pela metade
  62:                         Matrix3D mtdEscala = Matrix3DFactory.CreateScale(0.5, -0.5, 0.5);
  63:                         // Calcula a matriz final de transformação baseada no ponto centro original
  64:                         Matrix3D mtdFinal = mtdCentro * mtdEscala * dreResultado[0].Transformation;
  65:  
  66:                         // Calcula a projeção utilizando o SLARToolkit
  67:                         Matrix3D mtdViewPort = Matrix3DFactory.CreateViewportTransformation(Viewport.ActualWidth, Viewport.ActualHeight);
  68:                         Matrix3D mtdProjecao = Matrix3DFactory.CreateViewportProjection(mtdFinal, Matrix3D.Identity, cmkDetectorPattern.Projection, mtdViewPort);
  69:  
  70:                         // Aplicaca a transformação 3D ao objeto final
  71:                         imgMakesys.Projection = new Matrix3DProjection { ProjectionMatrix = mtdProjecao };
  72:                         imgMakesys.Visibility = Visibility.Visible;
  73:                     }
  74:                 });
  75:             };
  76:         }
  77:  
  78:         private void Button_Click(object sender, RoutedEventArgs e)
  79:         {
  80:             // Efetua a requisição de acesso a WebCam
  81:             if (CaptureDeviceConfiguration.RequestDeviceAccess())
  82:             {
  83:                 cpsVideo.Start();
  84:             }
  85:         }
  86:     }
  87: }

Deixei o código bem comentado, note que estamos utilizando o objeto Matrix3D para adicionar uma projeção ao nosso grid que contém a imagem.

A grande mágica na realidade é realizada pelo SLARToolkit que identifica a imagem e dispara o delegate que criamos na linha 50.

Notem também que estamos utilizando Multi-Threading para renderizar a projeção, isso evita que a aplicação trave com o processamento.

Abaixo uma imagem minha(galã!!!) utilizando o código acima.

image

Agora o código final para você brincarem :)

 

Get Microsoft Silverlight

 

 

Segue o fonte: SLRealidadeAumentada.zip (618,51 kb)

Até a próxima

Silverlight 4 Dica do dia #4 – Capturando as imagens da Webcam

By rdorta at junho 18, 2010 13:54
Filed Under: Arquitetura, Silverlight
&g

Olá,

Hoje vou mostrar para vocês como capturar as imagens camera do usuário no Silverlight.

Primeiro vamos ao XAML:

   1: <UserControl x:Class="SLWebCam.MainPage"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   5:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   6:     mc:Ignorable="d"
   7:     d:DesignHeight="550"t; d:DesignWidth="700"
-CRLF-->
   8:     Loaded="UserControl_Loaded">
   9:  
  10:     <Grid x:Name="LayoutRoot" Background="White">
  11:         <StackPanel>
  12:             <Grid Width="640" Height="480">
  13:                 <Rectangle Name="Viewport" Stroke="Black" StrokeThickness="2" />
  14:             </Grid>
  15:             <Button Content="IniciarCaptura" HorizontalAlignment="Center" Click="Button_Click" />
  16:         </StackPanel>
  17:     </Grid>
  18: </UserControl>

 

Notem que temos neste XAML apenas 2 controles, 1 Rectangle, que servirá de ViewPort para a câmera ou seja, onde será exibida a imagem da camera e um obtão que irá disparar o início da captura.

Agora vamos ao código:

   1: using System.Windows;
   2: using System.Windows.Controls;
   3: using System.Windows.Media;
   4:  
   5: namespace SLWebCam
   6: {
   7:     public partial class MainPage : UserControl
   8:     {
   9:         CaptureSource cpsVideo;
  10:  
  11:         public MainPage()
  12:         {
  13:             InitializeComponent();
  14:         }
  15:  
  16:         private void UserControl_Loaded(object sender, RoutedEventArgs e)
  17:         {
  18:             // Instancia o objeto que manipula a WebCam
  19:             cpsVideo = new CaptureSource();
  20:             // Define qual webcam será o alvo do objeto, no caso a câmera padrão do Sistema
  21:             cpsVideo.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
  22:  
  23:             //Cria o objeto que recebe os dados do video
  24:             VideoBrush vbsVideo = new VideoBrush();
  25:             vbsVideo.SetSource(cpsVideo);
  26:             // Preenche o retangulo com os dados capturados do video
  27:             Viewport.Fill = vbsVideo;
  28:         }
  29:  
  30:         private void Button_Click(object sender, RoutedEventArgs e)
  31:         {
  32:             // Efetua a requisição de acesso a WebCam
  33:             if (CaptureDeviceConfiguration.RequestDeviceAccess())
  34:             {
  35:                 cpsVideo.Start();
  36:             }
  37:         }
  38:     }
  39: }

Os grandes objetos que fazem a mágica são o CaptureSource, CaptureDeviceConfiguration e o VideoBrush.

Primeiro, instanciamos o CaptureSource e definimos qual camera ele irá utilizar atraves do CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice().

Depois criamos o VideoBrush e informamos a ele que sua fonte de imagens é o recém-criado CaptureSource.

Definimos que a saída do VideoBrush será o retangulo que criamos no XAML.

Pedimos a permissão do usuário para usar a câmera e pronto!!!

Muito easy esse tal de Silverlight.

Silverlight 4 Dica do dia #2 - Isolated Storage

By rdorta at junho 12, 2010 10:18
Filed Under: Silverlight, Arquitetura

Olá pessoal,

Vamos a mais uma dica do dica, utilizando o Isolated Storage como cache de arquivos no computador do client,

O que é Isolated Storage?

O Isolated Storage é um sistema de arquivos que o Silverlight usa, para armazenar dados/arquivos no computador do client da aplicação. É uma espécie de “cache” , onde você pode guardar strings, para serem recuperados a qualquer momento de sua aplicação.

É interessante usar em cenários onde você quer que o seu usuário visualize alguns dados de uma forma mais rápida. Como todo tipo de acesso a dado realizado pelo SIlvelright é dado através de serviços, você pode guardar o retorno de algum serviço no Isolated Storage para uma exibição mais rápida.

Como Funciona?

O Isolated Storage precisa ser habilitado pelo usuário do Silverlight, já que o mesmo utiliza arquivos físicos dentro da máquina para guardar as informações.

Para verificar as configurações referentes ao Isolated Storage, basta o usuário clicar com o botão direito na aplicação Silverlight, selecionar Silverlight, navegar até Application Storage e habilitar o uso do storage:

image

Abaixo um link com uma introdução legal ao Isolated Storage (em inglês):

http://msdn.microsoft.com/en-us/library/3ak841sy(VS.80).aspx

I Want Some CODE!!!

Então vamos lá:

Abaixo segue o código de 2 métodos simples para Salvar e Carregar dados do Isolated Storage:

Salvar Dados:

   1: private void SalvarDados(string pstrDados, string pstrNomeArquivo)
   2:         {
   3:  
   4:             using (IsolatedStorageFile objStorage = IsolatedStorageFile.GetUserStoreForApplication())
   5:             {
   6:                 using (IsolatedStorageFileStream objStreamStorage = new IsolatedStorageFileStream(pstrNomeArquivo, FileMode.OpenOrCreate, objStorage))
   7:                 {
   8:  
   9:                     using (StreamWriter objWriter = new StreamWriter(objStreamStorage))
  10:                     {
  11:                         sw.Write(pstrDados);
  12:                         sw.Close();
  13:                     }
  14:                 }
  15:             }
  16:         }

Carregar Dados:

   1: public string CarregarDados(string pstrNomeArquivo)
   2: {
   3:     string strRetorno = String.Empty;
   4:  
   5:     try
   6:     {
   7:         using (IsolatedStorageFile objStorage = IsolatedStorageFile.GetUserStoreForApplication())
   8:         {
   9:             using (IsolatedStorageFileStream objStreamStorage = new IsolatedStorageFileStream(pstrNomeArquivo, FileMode.Open, objStorage))
  10:             {
  11:                 using (StreamReader objReader = new StreamReader(objStreamStorage))
  12:                 {
  13:                     string strLinha = String.Empty;
  14:                     while ((strLinha = objReader.ReadLine()) != null)
  15:                         strRetorno += strLinha;
  16:                 }
  17:             }
  18:         }
  19:  
  20:         return strRetorno;
  21:     }
  22:     catch (Exception ex)
  23:     {
  24:         return string.Empty;
  25:     }
  26: }

Lembrando que você pode criar diretórios para sua aplicação, dentro do sistema de arquivos do Isolated Storage.

Em breve posto algum exemplo mais complexo de utilização.

Espero que seja útil.

Até a próxima!!!!

I´m back. Silverlight 4 Dica do dia #1 – Realizando impressões com o SIlverlight

By rdorta at junho 11, 2010 15:53
Filed Under: Silverlight

Olá pessoal!!!

Após algum tempo afastado, que realmente foi necessário, estou voltando a publicar novamente.

Estive envolvido em grandes projetos com Silverlight, utlizando muita coisa de SL, WCF RIA Services e mais.

Dei uma cara nova ao blog, mais light e profissional, e estou lançando séries de dicas rápidas e demos mais complexas em Silverlight.

Inaugarando a série, algo que me foi muito útil em alguns projetos, impressão em Silverlight.

Nas outras versões do Silverlight as impressões de relatórios tinham de ser feitas por algum meio externo como por exemplo HTML.

Agora com o Silverlight 4 nossa vida foi muito facilitada já que agora temos uma classe que imprime diretamente o conteúdo de algum objeto do nosso sistema.

Portanto você pode montar um relatório dentro de qualquer painel como um Grid ou StackPanel, e imprimir exatamente o que está dentro desse painel(imagens, controles etc…), utilizando o código abaixo

   1: PrintDocument doc = new PrintDocument();
   2: doc.DocumentName = "Teste de Impressão 1";
   3: doc.PrintPage += new EventHandler<PrintPageEventArgs>(doc_PrintPage);
   4: doc.Print();

2 coisas com o código acima chamam a nossa atenção:

1) Onde estou definindo o que vou imprimir?

2) Que evento PrintPage é esse?

 

Acontece que no Silverlight 4 existe um fluxo de impressão que é seguido, utilizando o código acima, quando enviamos o comando Print para o objeto PrintDocument o fluxo abaixo é seguido:

1) Um dialog de escolha de impressora é exibido ao usuário.

2) O usuário escolhe uma impressora

3) o Evento PrintPage é disparado, recebendo como parametro os dados da impressora selecionada.

Agora abaixo, o código de como lidar com a impressão:

   1: void doc_PrintPage(object sender, PrintPageEventArgs e)
   2: {
   3:  
   4:   // Define o objeto que será impresso, no caso tenho um StackPanel em meu XAML com o nome de stkPainelImpressao
   5:   e.PageVisual = stkPainelImpressao;
   6:  
   7:   // Especifica se existem mais páginas a serem impressas.
   8:   e.HasMorePages = false;
   9: }

Pronto!!! Seu objeto cheio de imagens e textos sobrepostos está sendo impresso!!!

Note que você pode controlar quantas páginas devem ser impressas através da propriedade HasMorePages além disso você pode delimitar o seu objeto de acordo com o tamanho da página da impressora escolhida, utilizando a propriedade PrintableArea.

Espero que gostem, vou continuar postando diversas dicas simples nessa série, e em breve venho com alguns demos mais complexos utilizando RIA Services para o desenvolvimento de aplicações de negócio.

[]´s

Screen Casts sobre Prism

By rdorta at outubro 28, 2009 10:31
Filed Under: Arquitetura, Silverlight

No Channel 9 está disponível uma série de screencasts sobre Prism.

http://channel9.msdn.com/posts/mtaulty/Prism--Silverlight-Part-1-Taking-Sketched-Code-Towards-Unity/

image

Começa falando de diversas coisas legais de arquitetura como injeção de dependência com Unity e depois leva isso ao mundo do Silvelrlight utilizando Prism

image

 

Muito boa referencia para quem está começando a se aprofundar no mundo de Silverlight e WPF.

Até a próxima Arqinovação

Exibição de página para quem não tem o plugin do Silverlight instalado – Parte 1 - .Net

By rdorta at outubro 27, 2009 14:56
Filed Under: Arquitetura, Silverlight

Ainda vejo muitos sites por aí, sofrerem com a publicação de sites em Silverlight. Eu digo sofrerem porque na verdade são “sofríveis” para quem não tem o plugin Silverlight instalado.

Não culpo os usuários finais. Imaginem a situação, você entra em um site feito e silverlight e da de cara com:

image 

UOU!!! Que máximo!! Parece um vírus!!! Quem vai clicar nisso???? Ninguém!!!

No assistente do Extra.com utilizamos uma técnica simples mas que ficou muito legal.

Olhem a diferença:

image

Isso chama a atenção, mostra que vale a pena instalar o Silverlight para ver o que é isso, incentiva as pessoas a instalarem o plugin.

Como obter esse resultado? Simples… principalmente se sua aplicação for criada em .Net.

Basta utilizar a tag abaixo e colocar o html que você deseja. Em tempo, não se pode usar dentro dessa tag scripts, apenas html.

<asp:Silverlight Windowless="true" ID="Xaml1" runat="server" Source="SeuSilverlight.xap"
                    MinimumVersion="2.0.31005.0" Width="100%" Height="100%">
                        <PluginNotInstalledTemplate>
                                SEU HTML AQUI!!!!
                        </PluginNotInstalledTemplate>
</asp:Silverlight>

Portanto a grande chave é utilizar a tag  <PluginNotInstalledTemplate> em seu silvelright, colocando ali o html que deseja exibir para o usuário da aplicação.

Vamos ajudar nossos usuários a entender o que eles precisam fazer para ter uma excelente experiência com nossas aplicações Silverlight.

Até a próxima Arqinovação!!!

Sobre mim

Ricardo Dorta

Ricardo Dorta

Arquiteto de sistemas da Makesys, atua na área de desenvolvimento de aplicações .NET há 5 anos.
MCP, MCAD e MCSD.