data binding com windows phone
DESCRIPTION
Este tutorial demonstra como desenvolver aplicativos para Windows Phone utilizando o recurso de Data BindingTRANSCRIPT
DESENVOLVIMENTO DE APLICATIVOS MÓVEIS
COM WINDOWS PHONE
Data Binding
Prof. Paulo Vinícius Moreira Dutra ([email protected])
1ª Edição
Muriaé/2012
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
2
Data Binding com Windows Phone
Muitas aplicações atuais trabalham com algum tipo de dado, sejam eles provenientes de
banco de dados físico ou informações que estejam armazenadas em memória. A habilidade de
uma aplicação conectar a algum elemento de dados é um recurso essencial em qualquer
aplicação. Dentro os recursos utilizados com Windows Phone é o Data Binding (vinculação de
dados), recurso que faz parte da tecnologia WPF (Windows Presentation Fundation). O Data
Binding permite vincular propriedades de um objeto a diversas fontes de dados.
Um exemplo de Data Binding pode ser a vinculação da propriedade Text de um componente
TextBox a uma propriedade de um objeto. O valor do TextBox é inicializado com o conteúdo
da propriedade vinculada e, quando o valor do TextBox é modificado, o valor do objeto
também é alterado.
Data Binding com objetos
A forma mais simples de vincular a propriedade de um componente TextBox é entre a
propriedade de um objeto, para isso, basta informar qual propriedade em que se quer
vincular. Por exemplo, para vincular a propriedade Text do TextBox à propriedade Descricao
de uma classe chamada Produto podemos realizar da seguinte maneira utilizando XAML:
<TextBlock Text="{Binding Path=Descricao}" TextWrapping="Wrap"/>
A propriedade Path da declaração Binding indica qual propriedade que será utilizada para
preencher o conteúdo do TextBox.
Para demonstrar melhor a funcionalidade do Data Binding, abra Visual Studio com suporte
para desenvolvimento de aplicações Windows Phone, crie um novo projeto chamado
ExemploDataBinding e selecione o template Windows Phone Application.
A primeira coisa a ser fazer é criar um classe chamada Pessoa.cs
public class Pessoa { private string _nome; private string _telefone; private int _idade; private int _sexo; public string Nome { get { return _nome; } set { _nome = value; } } public string Telefone { get { return _telefone; } set { _telefone = value; } } public int Idade {
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
3
get { return _idade; } set { _idade = value; } } public int Sexo { get { return _sexo; } set { _sexo = value; } } }
Listagem 1 – Pessoa.cs
Agora como próximo passo desenhe um layout conforme a figura 1 ou altere o arquivo
MainPage.xaml do código da listagem listagem 2 para listagem listagem 3.
Figura 1 – Layout interface
<!--LayoutRoot is the root grid where all page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel>
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
4
<!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid> </Grid>
Listagem 2
<!--LayoutRoot is the root grid where all page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="Exemplo Data Binding" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="Data Binding" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel Height="438" HorizontalAlignment="Left" Margin="9,24,0,0" Name="panelDados" VerticalAlignment="Top" Width="441" DataContext="{Binding Pessoa}"> <TextBlock Height="30" Name="textBlock1" Text="Nome" /> <TextBox Height="71" Name="txtNome" Text="TextBox" Width="Auto" /> <TextBlock Height="30" Name="textBlock2" Text="Telefone" /> <TextBox Height="71" Name="txtTelefone" Text="TextBox" Width="Auto" /> <Grid Height="127" Name="grid1" Width="Auto"> <Grid.RowDefinitions> <RowDefinition Height="44" /> <RowDefinition Height="116*" /> </Grid.RowDefinitions> <TextBlock Height="30" HorizontalAlignment="Left" Margin="6,6,0,0" Name="textBlock3" Text="Sexo" VerticalAlignment="Top" Width="297" /> <StackPanel Grid.Row="1" Height="Auto" HorizontalAlignment="Stretch" Margin="5" Name="stackPanel2" VerticalAlignment="Stretch" Width="Auto" Orientation="Horizontal"> <RadioButton Content="Feminino" Height="Auto" Name="rdbFeminino" /> <RadioButton Content="Masculino" Height="Auto" Name="rdbMasculino" /> </StackPanel> </Grid> <TextBlock Height="30" Name="textBlock4" Text="Idade" /> <TextBox Height="71" Name="txtIdade" Text="TextBox" Width="460" /> </StackPanel> <Button Content="Exibir" Height="72" HorizontalAlignment="Left" Margin="81,486,0,0" Name="btnExibir" VerticalAlignment="Top" Width="264" /> </Grid> </Grid>
Listagem 3
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
5
Com o layout pronto podemos iniciar o processo de vinculação do objeto do tipo Pessoa com
os componentes da interface. Para que a vinculação ocorre de maneira correta é necessário
vincular a página do aplicativo ou painel a um contexto. Esse contexto diz em qual fonte de
dados os componentes da interface estão vinculados, para isso vamos utilizar a propriedade
DataContext. Todos os componentes de interface possuem essa propriedade, entretanto se
diversos componentes estiverem em um container, como por exemplo, StackPanel, os
componentes que estiveram nesse container também estarão vinculados ao mesmo contexto.
Se você observar a listagem listagem 3, os componentes TextBox, TextBlock e RadioButton
foram adicionados dentro de um StackPanel.
<StackPanel Height="438" HorizontalAlignment="Left" Margin="9,24,0,0" Name="panelDados" VerticalAlignment="Top" Width="441" DataContext="{Binding Pessoa}">
Listagem 4
Observe que o componente StackPanel contém a propriedade DataContext vinculado ao
objeto Pessoa que indica a origem da fonte de dados, que neste caso é a classe Pessoa. Essa
vinculação também pode ser realizada via linha de código. Esse é um panel onde os demais
componentes foram adicionados, desta forma, todos os componentes também irão fazer parte
do mesmo contexto. Sempre que houver a necessidade de alterar a instância do objeto ao qual
o contexto foi vinculado, deve-se alterar o valor da propriedade DataContext do componente
com a nova instância do objeto. Caso seja necessário você pode definir um DataContext de
forma individual para os componentes ao invés de um container principal.
Vinculando componentes
Para todos os componentes TextBox será necessário dizer em qual atributo do objeto do tipo
Pessoa eles estarão vinculados. A vinculação é definida na propriedade do componente que
você quer alterar o valor de acordo com a fonte de origem, neste caso, a propriedade Text.
Observe que a propriedade Text do objeto txtNome, contém a palavra reservada Binding
entre chaves, seguido do nome da propriedade que está sendo vinculada.
<TextBox Height="71" Name="txtNome" Text="{Binding Path=Nome}" Width="Auto" />
Listagem 5 Repita o mesmo procedimento para o objeto txtTelefone, listagem 6, e txtidade, listagem 7. <TextBox Height="71" Name="txtTelefone" Text="{Binding Path=Telefone}" Width="Auto" />
Listagem 6 <TextBox Height="71" Name="txtIdade" Text="{Binding Path=Idade}" Width="460" />
Listagem 7
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
6
Testando a vinculação com os componentes TextBox
Com a vinculação definida nos componentes TextBox, iremos implementar um trecho de
código que irá testar se a vinculação ocorreu com sucesso, para isso será necessário criar uma
instância da classe Pessoa e atribuir o objeto a propriedade DataContext do componente
StackPanel que contém os demais componentes.
Crie a instância da classe Pessoa na seguinte seção da aplicação
namespace ExemploDataBinding { public partial class MainPage : PhoneApplicationPage { private Pessoa pessoa; ---------- Declarar esse objeto
Listagem 8 – Declarando objeto do tipo Pessoa
Acesse o arquivo MainPage.xaml em modo de designer, selecione o página principal ou em
Document Outline selecione o item PhoneApplicationPage. Caso a guia Document Outline
não esteja visível, pressione as teclas Ctrl + Alt + T.
Figura 2 – Document Outline
Após selecionar a página principal acesse a janela de propriedades e a guia Events, nesta guia
de um duplo clique no evento Loaded para gerar um método que será associado a esse
evento. O evento Loaded é executado sempre que a página da aplicação é carrega.
Figura 3 – Properties
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
7
Digite o seguinte trecho de código da listagem 9 no evento gerado:
pessoa = new Pessoa(); pessoa.Nome = "Paulo Vinícius"; pessoa.Idade = 29; pessoa.Telefone = "555-5555"; pessoa.Sexo = 1; panelDados.DataContext = pessoa;
Listagem 9
Ao executar a aplicação observe que os valores informados nas propriedades do objeto são
refletidos nos componentes.
Agora pare a aplicação, de um duplo clique sobre o botão Exibir para gerar o evento de click e
digite o seguinte trecho de código.
MessageBox.Show("Nome: " + pessoa.Nome + "\n" + "Idade: " +pessoa.Idade + "\n" + "Telefone: " + pessoa.Telefone + "\n" + "Sexo: " + pessoa.Sexo);
Listagem 10 – Código para evento Click do botão Exibir.
Execute a aplicação novamente e experimente alterar o conteúdo das caixa de texto e logo em seguida clique no botão Exibir. Observe que será exibida uma mensagem, mas as modificações realizadas nos componentes não refletiram nas propriedades do objeto, esse problema ocorre, pois a vinculação apenas é realizada em uma única direção, ou seja, da propriedade do objeto para o componente da interface. Para alterar o modo de vinculação devemos modificar a propriedade Binding de cada componente. A listagem 11 contém o trecho de código que representa os componentes TextBox e a propriedade Binding acrescida do atributo Mode como TwoWay. Dessa forma qualquer alteração nos componentes da interface ira atualizar as propriedades do objeto e vice-versa. <TextBox Height="71" Name="txtNome" Text="{Binding Path=Nome, Mode=TwoWay}" Width="Auto" />
<TextBox Height="71" Name="txtTelefone" Text="{Binding Path=Telefone, Mode=TwoWay}" Width="Auto" />
<TextBox Height="71" Name="txtIdade" Text="{Binding Path=Idade, Mode=TwoWay}" Width="460" />
Listagem 11 – Alterando a propriedade binding de cada componente
Existem três modos de vinculação: OneWay: Atualiza a propriedade de destino, somente quando a propriedade de origem for alterada TwoWay: Atualiza a propriedade de destino ou de origem, sempre que o valor de destino ou origem for alterado. OneTime: Atualiza somente quando a aplicação é iniciada.
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
8
Vinculando componentes Radio Buttons
A vinculação com os componentes RadioButtons irá ocorrer de uma maneira um pouco
diferente realizado com as caixas de texto. A propriedade Sexo da classe Pessoa armazena
somente valores inteiros enquanto os componentes radiobuttons aceitam somente valores
booleanos, esses tipos são incompatíveis já que nesta aplicação quando o usuário selecionar o
campo Feminino deve ser armazenado valor 1 no atributo Sexo, caso seja masculino, armazena
o valor 2. Devemos tornar esses tipos intercambiáveis. Para isso, devemos implementar um
conversor, pois se quisermos por exemplo, ativar o botão de opção Feminino quando o valor
da propriedade Sexo for igual a 1.
No Visual Studio, crie uma classe chamada SexoConverter, logo em seguida importe os
namespace System.Windows.Data e System.Globalization. Implemente a interface
IValueConverter na classe SexoConverter. Essa classe irá converter um valor booleano para
inteiro e de inteiro para booleano.
public class SexoConverter : IValueConverter { }
Listagem 11 – Interface IValueConverter
Clique com o botão direito do mouse sobre IValueConverter, selecione a opção Implement
Interface para criar o corpo do método para essa interface.
Figura 4 – Gerando o corpo dos métodos
O método Convert converte os valores da propriedade de binding para ser apresentado no botão de opção, já o método ConvertBack converter o valor selecionado no botão de opção de acordo com tipo da propriedade vinculada. O desenvolvedor é responsável por implementar a lógica de conversão dos dados.
public class SexoConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
9
}
Listagem 12 – Métodos da interface IValueConverter
Agora altere os método Convert e ConvertBack de acordo com a listagem 13. Após
implementar os métodos compile o seu projeto para que possamos acessar a classe converter
através da janela de propriedades.
public class SexoConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { int sexo = Int32.Parse(value.ToString()); if ( (parameter.Equals("F") && (sexo == 1) ) || (parameter.Equals("M") && (sexo == 2) ) ) return true; else return false; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { if (parameter.Equals("M")) return 2; else if (parameter.Equals("F")) return 1; return 0; } }
Listagem 13 – Implementado os métodos Convert e ConvertBack
Após compilar o seu projeto acesse o arquivo MainPage.xaml e localize os objetos rdbFemino
e rdbMasculino e faça a seguinte alteração da listagem 14 nos objetos, vinculando a
propriedade IsChecked a propriedade Sexo do objeto Pessoa.
<RadioButton Content="Feminino" Height="Auto" Name="rdbFeminino" IsChecked="{Binding Path=Sexo, Mode=TwoWay}" /> <RadioButton Content="Masculino" Height="Auto" Name="rdbMasculino" IsChecked="{Binding Path=Sexo, Mode=TwoWay}"/>
Listagem 14 – Vinculando os botões de opção à propriedade do objeto
Agora como próximo passo, devemos atribuir o conversor para cada botão de opção, para isso
acesse a página MainPage.xaml em modo de designer e selecione o componente rdbFeminino
e logo em seguida acesse a janela de propriedades. Na janela de propriedades localize e clique
na propriedade Checked e selecione a opção do menu Apply Data Binding..., figura 5, na
janela seguinte, figura 6, selecione a opção Converter, por fim clique na opção Create New...,
será solicitado que seja definido o nome da instância do conversor selecionado, figura 7. Com
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
10
o objeto conversor criado defina o valor do parâmetro como “F”, figura 8. Repita o mesmo
processo para o objeto rdbMasculino, sendo que defina o nome do conversor como
sexoConverterMasculino e defina no campo Parameter o valor ”M”, figura 9.
Figura 5 – Selecionando propriedade
Figura 6 – Selecionando o objeto Converter
Figura 7 – Definindo o nome do objeto converter
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
11
Figura 8 – Definindo o parâmetro para o converter do objeto rdbFeminino.
Figura 9 – Definindo o parâmetro para o converter do objeto rdbMasculino
Após vincular os componentes RadioButtons, verifique se no arquivo MainPage.xaml se a
implementação dos objetos esta conforme a listagem 15.
<RadioButton Content="Feminino" Height="Auto" Name="rdbFeminino" IsChecked="{Binding Path=Sexo, Mode=TwoWay, Converter={StaticResource sexoConverterFeminino}, ConverterParameter=F}" /> <RadioButton Content="Masculino" Height="Auto" Name="rdbMasculino" IsChecked="{Binding Path=Sexo, Mode=TwoWay, Converter={StaticResource sexoConverterMasculino}, ConverterParameter=M}"/>
Listagem 15 – Vinculando os botões de opção à propriedade do objeto
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
12
Implementando eventos na classe Pessoa
Na seção anterior verificamos que ao criar um objeto do tipo Pessoa e atribuir ao contexto, os
valores dos componentes da interface foram atualizados com os valores das propriedades do
objeto. Essa alteração ocorreu somente quando iniciamos a aplicação. Mas se modificarmos os
valores do objeto em tempo de execução? Será que os valores dos componentes vinculados à
propriedade do objeto também serão alterados? Para verificar se realmente os valores dos
componentes são alterados vamos realizar um pequeno teste. Acesse o designer do arquivo
MainPage.xaml e adicione um botão chamado Visualizar, conforme a figura 10, e defina o
nome do objeto como btnVisualizar. Após adicionar o botão, de um duplo clique e adicione o
código da listagem 16 no evento gerado.
Figura 10 – Adicionando o botão Visualizar
pessoa.Nome = "Fulano de Tal"; pessoa.Idade = 28; pessoa.Telefone = "444-44444"; pessoa.Sexo = 2;
Listagem 16 – Código para o botão Visualizar
Ao executar o aplicativo e clicar no botão visualizar nenhum valor será alterado, isso ocorre,
pois as propriedades não possuem mecanismos para notificar quando o valor da propriedade
do objeto muda. Para que ocorra alterações nos componentes de interface no qual as
propriedade do objeto estão vinculadas, será necessário implementar um evento que notifica
quando o valor da propriedade de um objeto é alterada. Acesse a classe Pessoa, importe o
namespace System.ComponentModel e altere a classe conforme a listagem 17.
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
13
public class Pessoa : INotifyPropertyChanged { private string _nome; private string _telefone; private int _idade; private int _sexo; public string Nome { get { return _nome; } set { if (value != _nome) { _nome = value; NotifyPropertyChanged("Nome"); } } } public string Telefone { get { return _telefone; } set { if (value != _telefone) { _telefone = value; NotifyPropertyChanged("Telefone"); } } } public int Idade { get { return _idade; } set { if (value != _idade) { _idade = value; NotifyPropertyChanged("Idade"); } } } public int Sexo { get { return _sexo; } set { if (value != _sexo) { _sexo = value; NotifyPropertyChanged("Sexo"); } } } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String propertyName)
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
14
{ PropertyChangedEventHandler handler = PropertyChanged; if (null != handler) { handler(this, new PropertyChangedEventArgs(propertyName)); } } }
Listagem 17 – Implementando eventos na classe Pessoa
Agora vamos entender as modificações:
A interface INotifyPropertyChanged pertence ao namespace System.ComponentModel. Essa
interface é utilizada quando queremos notificar sobre mudanças ocorridas nos valores das
propriedades dos objetos, modificações que gera o evento PropertyChanged, listagem 19, que
deve ser definido ao implementar a interface.
O método NotifyPropertyChanged, foi criado para facilitar as notificações dos eventos
ocorridos na classe Pessoa. Esse método é chamado para cada propriedade do objeto para
notificar quando o seu valor é alterado, listagem 20.
public class Pessoa : INotifyPropertyChanged
Listagem 18 – Classe pessoa implementando a interface INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (null != handler) { handler(this, new PropertyChangedEventArgs(propertyName));
} }
Listagem 19 – Implementação do evento PropertyChanged
set { if (value != _nome) { _nome = value; NotifyPropertyChanged("Nome");
} }
Listagem 20 – Notificando a mudança do valor da propriedade
Agora execute a aplicação é verifique que os valores dos componentes são alterados quando o
botão Visualizar é adicionado, figura 11.
Apostila - Desenvolvimento de Aplicativos Móveis com Windows Phone: Data Binding
15
Figura 11 – Aplicação em execução – Mudando os valores dos componentes