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

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.