BrSilverlight

Tutoriais e dicas sobre Silverlight

Sobre o autor

Sou Breno Ferreira, desenvolvedor em um Centro de Tecnologia em Petrópolis especializado em Silverlight. Criei este site com o objetivo de postar dicas, tutoriais e artigos sobre Silverlight, WPF e tecnologias Microsoft.

 

Formulários em Silverlight com o controle DataForm

Introdução

O Silverlight é uma plataforma muito boa para construção de aplicações Line-of-Business, que oferecem uma interface rica e que responde rapidamente ao usuário.

Neste tutorial, irei explicar como criar um formulário de cadastro em Silverlight, usando o controle DataForm, e aplicando o Pattern MVVM para expor os dados ao UserControl do Silverlight. Caso voce não conheça o pattern, leia um tutorial postado anteriormente neste site que explica como o pattern funciona.

O código deste tutorial está disponível no meu Skydrive:

http://cid-1498c467c14dc20b.skydrive.live.com/self.aspx/BrSilverlight/Tutoriais/GameStore.zip

Criando o projeto

Como nossa aplicação será um esboço de uma aplicação LOB, criaremos uma NavigationApplication, que já inclui por padrão um sistema de navegação, parecido com páginas Web. Apesar de termos somente uma “página” nesta aplicação, acho que esse padrão é interessante para aplicações LOB.

Para criar um projeto do tipo NavigationApplication, vá em New Project no Visual Studio, e escolha a opção Silverlight Navigation Application.

image

Model

Neste tutorial, iremos criar um formulário para cadastro de jogos. Iremos guardar dados como nome, numero de jogadores, categoria, avaliação e a URL do site.

Crie uma nova classe chamada Game e adicione as seguintes propriedades.

Game.cs
  1. public class Game
  2. {
  3.     [Required(ErrorMessage="Game name is required")]
  4.     public String Name { get; set; }
  5.  
  6.     [RegularExpression(@"((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)", ErrorMessage="Invalid Website ULR")]
  7.     public String Website { get; set; }
  8.  
  9.     [Required(ErrorMessage="Number of Players is required")]
  10.     public int NumberOfPlayers { get; set; }
  11.  
  12.     [Range(0, 1)]
  13.     public Double Rating { get; set; }
  14.  
  15.     [Required(ErrorMessage="Category is required")]
  16.     public String Category { get; set; }
  17. }

 

Snippet 1

Essa classe será o Model na nossa aplicação, guardando as informações dos games.

Obs: Note que as propriedades estão marcadas com alguns Attributes. Ignore

ViewModel

O ViewModel neste exemplo será bastante simples. Será utilizado somente para expor os dados para a nossa View. Adicione a classe GameViewModel ao projeto e o seguinte código:

GameViewModel.cs
  1. public class GameViewModel : INotifyPropertyChanged
  2. {
  3.     public GameViewModel()
  4.     {
  5.         this.CreateGames();
  6.     }
  7.  
  8.     private void CreateGames()
  9.     {
  10.         List<Game> games = new List<Game>();
  11.  
  12.         Game game1 = new Game();
  13.         game1.Name = "Halo 3";
  14.         game1.Rating = 1;
  15.         game1.NumberOfPlayers = 4;
  16.         game1.Website = "http://halo.xbox.com/halo3/";
  17.         var game1Category = "Shooter";
  18.         game1.Category = game1Category;
  19.  
  20.         games.Add(game1);
  21.  
  22.         Game game2 = new Game();
  23.         game2.Name = "Gears of War 2";
  24.         game2.Rating =0.8;
  25.         game2.NumberOfPlayers = 10;
  26.         game2.Website = "http://gearsofwar.xbox.com/";
  27.         game2.Category = game1Category;
  28.  
  29.         games.Add(game2);
  30.  
  31.         Game game3 = new Game();
  32.         game3.Name = "Fifa Soccer 10";
  33.         game3.Rating = 0.7;
  34.         game3.NumberOfPlayers = 4;
  35.         game3.Website = "http://fifa.easports.com/";
  36.  
  37.         var game3Category = "Sports";
  38.         game3.Category = game3Category;
  39.  
  40.         games.Add(game3);
  41.  
  42.         this.Games = games;
  43.     }
  44.  
  45.     private List<Game> games;
  46.     public List<Game> Games
  47.     {
  48.         get { return games; }
  49.         private set { games = value; OnPropertyChanged("Games"); }
  50.     }
  51.  
  52.     public event PropertyChangedEventHandler PropertyChanged;
  53.  
  54.     private void OnPropertyChanged(String propertyName)
  55.     {
  56.         if (this.PropertyChanged != null)
  57.             this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  58.     }
  59. }

 

 

 

Snippet 2

No nosso ViewModel, criamos uma propriedade chamada Games do tipo List<Game>. Essa propriedade será utilizada pela nossa View para mostrar os dados dos games cadastrados. O método CreateGames cria alguns objetos iniciais, somente para o objetivo de demonstração deste exemplo.

Obs: Note que esta classe implementa a interface INotifyPropertyChanged, que serve para notificar a View de que a propriedade do nosso ViewModel foi modificada, atualizando as informações na tela.

View

Como no nosso projeto iremos utilizar alguns controles do Silverlight Tookit, iremos adicionar as seguintes DLLs ao nosso projeto:

  • System.Windows.Controls.Data.DataForm.Toolkit.dll
  • System.Windows.Controls.Input.Toolkit.dll

Como na versão Beta 2 do Visual Studio 2010 há um pequeno bug na hora de adicionar referências a DLLs, voce terá que navegar até a pasta onde está instalado o Silverlight Control Toolkit e adicionar as DLLs. Geralmente, o Toolkit está instalado em:

C:\Program Files\Microsoft SDKs\Silverlight\v4.0\Toolkit\Bin

Nossa View, que irá conter o controle DataForm, será o Home.xaml, na pasta Views do projeto. Adicione o Xaml abaixo no arquivo Home.xaml.

Code Snippet
  1. <navigation:Page x:Class="GameStore.Home"
  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" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  5.     xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
  6.     xmlns:dt="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
  7.     xmlns:in="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"
  8.     xmlns:vm="clr-namespace:GameStore.ViewModel"
  9.     mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"
  10.     Title="Home"
  11.     Style="{StaticResource PageStyle}">
  12.     
  13.     <UserControl.Resources>
  14.         <vm:GameViewModel x:Key="ViewModel" />
  15.     </UserControl.Resources>
  16.  
  17.     <Grid x:Name="LayoutRoot" DataContext="{StaticResource ViewModel}">
  18.         <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}">
  19.  
  20.             <StackPanel x:Name="ContentStackPanel">
  21.  
  22.                 <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}"
  23.                            Text="Welcome to the Game Store"/>
  24.  
  25.                 <dt:DataForm AutoGenerateFields="False" AutoEdit="False" ItemsSource="{Binding ElementName=LayoutRoot, Path=DataContext.Games}">
  26.                     <dt:DataForm.EditTemplate>
  27.                         <DataTemplate>
  28.                             <StackPanel dt:DataField.IsFieldGroup="True">
  29.                                 <dt:DataField Label="Name:" Description="Name of the game">
  30.                                     <TextBox Text="{Binding Path=Name, Mode=TwoWay}" />
  31.                                 </dt:DataField>
  32.                                 <dt:DataField Label="Website:" Description="Website of the game">
  33.                                     <TextBox Text="{Binding Path=Website, Mode=TwoWay}" />
  34.                                 </dt:DataField>
  35.                                 <dt:DataField Label="Number of Players" Description="Number of players supported by the game" >
  36.                                     <in:NumericUpDown Minimum="1" Value="{Binding Path=NumberOfPlayers, Mode=TwoWay}" Width="70" HorizontalAlignment="Left" />
  37.                                 </dt:DataField>
  38.                                 <dt:DataField Label="Rating" Description="How good is this game?">
  39.                                     <in:Rating ItemCount="5" Value="{Binding Path=Rating, Mode=TwoWay}" />
  40.                                 </dt:DataField>
  41.                                 <dt:DataField Label="Category" Description="Game category (Shooter, Sports, Action, ...)">
  42.                                     <TextBox Text="{Binding Path=Category, Mode=TwoWay}" />
  43.                                 </dt:DataField>
  44.                             </StackPanel>
  45.                         </DataTemplate>
  46.                     </dt:DataForm.EditTemplate>
  47.                 </dt:DataForm>
  48.  
  49.             </StackPanel>
  50.  
  51.         </ScrollViewer>
  52.     </Grid>
  53.  
  54. </navigation:Page>

Snippet 3

O controle DataForm

No Silverlight Tookit, existe um controle muito bom para a construção de formulários para receber dados do usuário. É um controle muito fácil de usar, e também muito flexível. Voce pode optar por gerar os campos automaticamente (setando a propriedade AutoGenerateFields para True), ou então especificar explicitamente quais controles serão utilizados para mostrar os dados. No nosso caso, setamos a propriedade AutoGenerateFields para false e customizamos a aparência do Form, definindo o EditTemplate do DataForm.

A maneira mais fácil de definir os controles utilizados no Form é criando um StackPanel que irá conter vários DataFields, que irão conter os Labels e terão como Content o controle que irá apresentar/receber a informação do usuário.

Nesse exemplo, temos vários DataFields, cada um com um controle Databound que irá apresentar/receber os dados do usuário. Por exemplo, utilizamos uma TextBox para o nome do game, um NumericUpDown para o número de jogadores, um Rating para a avaliação do jogo, etc… Note que em cada DataField setamos as propriedades Label (precisa explicar?) e Description (uma informação extra que é mostrada ao usuário sobre uma propriedade em particular.

Obs: usamos TwoWay Binding nos controles, assim quando o usuário editar as informações de um game, elas serão automaticamente atualizadas no noss Model.

Quando rodamos a aplicação, veremos o seguinte resultado:

image

 

 

 

 

Model Revisited

Lembra-se daqueles Attributes que definimos nas propriedades do nosso Model? Eles servem para fazermos validação dos dados digitados pelo usuário. Por exemplo:

O Attribute Required indica que o usuário precisa preencher o campo respectivo a propriedade marcada com esse Attribute. No nosso exemplo, as propriedades Name, NumberOfPlayers e Category. Esse Attribute também permite definir uma mensagem de erro que é apresentada ao usuário caso o usuário não preencha o campo.

Outro attribute interessante é o o RegularExpression, que permite que a validação de um campo através de uma Regular Expression. Usamos esse Attribute na propriedade Website, e definimos também uma ErrorMessage caso a Regex falhe.

Outro Attribute que também usamos é o Range, que define entre quais valores uma propriedade numérica pode estar.

Para saber mais sobre outros Attributes de validação, acesse a documentação do Namespace System.ComponentModel.DataAnnotations em http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx.

Quando inserimos alguma entrada inválida no DataForm, e clicamos em OK (quando editando ou adicionando um item novo), as mensagens de erro são automaticamente mostradas, conforme a imagem abaixo:

image 

 

Quando corrigimos os erros, e clicamos em OK, as mensagens somem e o novo game é adicionado a Collection no nosso ViewModel.

image


Categories: Silverlight
Permalink | Comentários (0) | Post RSSRSS comment feed

Comentários

Comentar




  Country flag

biuquote
  • Comentário
  • Pré-visualização
Loading