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 #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!!!!

Grande novidade do PDC - Silverlight 4

By rdorta at novembro 19, 2009 13:59
Filed Under: Arquitetura, Silverlight

Olá amigos,

Mais uma vez a Microsoft se supera no PDC 2009. Quem quiser um acompanhamento técnico legal do PDC 2009, sugiro o blog do Waldemir Cambiucci (ver no meu blogroll).

Agora falando sobre o que mais me interessa, Silverlight 4 vem aí e com features que eu sempre dizia que faltavam ao Silvelright quando comparado ao Flash. Ou seja… Flash Down…

Vamos direto ao link e depois vou comentar

http://silverlight.net/getstarted/silverlight-4-beta/

Primeiro ponto legal, a utilização do Visual Studio 2010.

Vamos aos Tools:

Silverlight 4 Beta Tools for Visual Studio 2010

Segundo ponto legal:

Blend for .Net 4

http://www.microsoft.com/downloads/details.aspx?FamilyID=6806e466-dd25-482b-a9b3-3f93d2599699&displaylang=en

A Documentação:

Online Silverlight 4 Beta Documentation

E agora minha visão sobre as novas features:

  • Impressão direta do Silverlight – YES WE CAN!!! muito bom!!!
  • Inclusão de um RichTextbox para exibição de HTML – Outra feature que fazia falta… Muito bom
  • DataGrid com Sort e Resize e Copy e Paste de linhas.
  • RIA Services
  • Melhorias no sistema de Out-of Browser.
  • Integração com periféricos: leitor de códigos de barra, webcam e outros..

Vou realziar alguns testes com a ferramenta em breve e posto mais comentários´

Até a próxima arqinovação.

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!!!

Catálogo BlackBox – ASP.NET MVC na veia.

By rdorta at outubro 27, 2009 14:04
Filed Under: Arquitetura, MVC

Mais um projeto de inovação da Makesys está no ar.

O Catálogo on-line da blackbox está no ar utilizando todo o requinte de aplicações desenvolvidas em ASP.NET MVC. Melhores práticas de SEO, Url Rewriting. Vale a pena conferir!!!

http://www.catalogoblackbox.com.br/

image

Sobre o projeto

Desenvolvido utilizando tecnologias de ponta como ASP.NET MVC e jquery, acompanhei este projeto desde o seu levantamento até o seu acabamento. Solução muito interessante e que em breve será evoluída para um e-commerce. Acompanhem :)

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

Física com Silverlight: YES WE CAN!!! – By William Machado

By rdorta at outubro 22, 2009 09:37
Filed Under: Arquitetura, Silverlight

Olá pessoal, abaixo segue um tutorial muito bom do meu colega de Makesys Willian, que tem se dedicado aos estudo de Silverlight. A equipe da Makesys vem melhorado muito seu conhecimento em Silverlight. Show!!! Obrigado William!!!!

Você vai precisar dos seguinte arquivo para trabalhar com física no Blend:

PhysicsHelper.3.0.0.3.zip (3,60 mb)

Abaixo o código fonte final:

Silverlight_Carro_Fisica.zip (521,23 kb)

By William Machado:

Tutorial: Desenvolvimento em Silverlight 3 utilizando física

No mundo do desenvolvimento de aplicativos baseados na Web, os usuários estão exigindo experiências de aplicativos cada vez mais aprimoradas.

Este tutorial mostra como podemos criar uma aplicação simples em SilverLight utilizando as leis da física. No nosso caso será um carro.

Bom antes de começar vamos entender como funciona. Farseer Physics Engine é um motor de física 2D

que suporta varias plataformas como o XNA da Microsoft, o Silverlight, WPF. Uma das características do Farseer Physics Engine é a simplicidade que permite a criação de diversas aplicações e jogos dinâmicos.

o Farseer Physics Engine é projetado para controlar a posição e rotação de objetos.
No mundo real, as coisas se movem e giram devido as forças aplicadas e torques. Em Farseer, é a mesma coisa. Objetos representam as coisas do mundo real. As forças e torques são aplicados e os organismos reagem de acordo com as leis da física 2D.

Crie um novo projeto selecionando “Silverlight 3 Application”.

clip_image002

Mude o tipo do “LayoutRoot” de “Grid” para “Canvas”.

clip_image004

Adicione o controle “PhysicsControllerBehavior” no LayoutRoot

clip_image006

Ative a propriedade: “MousePickEnabled” para manipular os objetos da tala com o mouse

clip_image008

Agora ou você pode desenhar o carro no próprio Blend ou adicionar uma imagem, no meu caso eu desenhei o carro e adicionei a imagem da roda.

clip_image010

Agrupar as imagens em “Canvas”

clip_image012

Para utilizar o recurso de física temos que incluir a “FarseerPhysics.dll” em nosso projeto.

clip_image014

Agora o projeto deve ser compilado para que os controles de física sejam adicionados no Blend.

clip_image016

Os novos controles que foram adicionados:

clip_image018

Clique e arraste o controle “PhysicsObjectBehavior” nos objetos que terão massa, nesse caso utilizei três uma para o Carro(Path) e outros dois para as rodas(Canvas).

Obs.: aplicar o “PhysicsObjectBehavior” somente nos Canvas das rodas e não nas imagens.

clip_image020

Desenhe um “Rectangle” para ser o chão e aplique o controle de física “PhysicsObjectBehavior”, mas ative a propriedade “IsStatic” do “PhysicsObjectBehavior” para que seja um objeto estático.

clip_image022

Para fazer um “Join” das rodas com o carro precisamos de um objeto intermediário para que possamos utilizar o controle “PhysicsJointBehavior” para isso vamos criar um circulo no meio da roda.

clip_image024

Arraste e solte o controle no circulo.

clip_image026

As propriedades do controle devem ficar assim:

clip_image028

Para isso você pode simplesmente clicar aqui arrastar e soltar encima do carro:

clip_image030

Ok, depois de ter feito o “Join” das rodas com o carro vamos aplicar força na roda para simular o funcionamento motor do carro, para isso precisamos do controle “PhysicsApplyTorqueBehavior”.

Clique arraste e solte o controle encima da roda

clip_image032

Nas propriedades clique em “New”, na seguinte janela escolha o evento “PhysicsKeyTrigger” (para utilizar os eventos do teclado)

clip_image034

 

Selecione uma tecla para acionar o controle

clip_image036

Adicione um valor para “ToqueValue” ex: -5000 para que a roda gire para a esquerda

clip_image038

Repita o mesmo procedimento adicione mais um controle “PhysicsApplyTorqueBehavior”, mas com o valor de “ToqueValue” 5000 para que a roda gire para a direita

clip_image040

Salve a aplicação (CTRL + S) compile (CTRL + SHIFT + B) e execute (F5)

Pronto temos um carro utilizando as leis da física em Silverlight.

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.