WPF - Data Binding - Revisando técnicas úteis
Neste artigo vou apresentar um resumo sobre o algumas técnicas úteis usando o databinding no WPF em cenários específicos de forma a refrescar sua memória e lhe fornecer subsídios para que você possa trabalhar com os controles WPF em cenários onde a vinculação de dados é necessária.
Todos os exemplos foram feitos usando o Visual Basic 2010 Express Edition.
Selecione o menu File -> New Project e a seguir escolha o modelo WPF_Application com o nome DataBinding_Cenarios;
Os componentes do DataBinding
- Target(Destino)
- È o objeto que vai usar o resultado da vinculação (binding);
- Target Property(Propriedade de destino)
- A propriedade de destino do objeto que irá utilizar o
resultado;
- Source (Origem) - O objeto que
fornece um valor para o objeto de destino usar;
- Path(Caminho) - Um caminho que
localiza o valor dentro do objeto de origem;
1- Binding com uma fonte relativa
A propriedade de vinculação RelativeSource permite que você especifique um objeto de origem através de sua relação com o controle de destino.
No código de exemplo a seguir temos uma vinculação da propriedade BackGround de um TextBox com sua propriedade Text. Quando você digita o nome de uma cor no TextBox, o controle usa esta cor para definir a sua cor de fundo.
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <TextBox Margin="10" Height="30" VerticalAlignment="Top" Background="{Binding RelativeSource={RelativeSource Self}, Path=Text}"/> </Grid> </Window> |
Uma fonte relativa pode também ser um:
2- Binding com classes no code-behind
Suponha que um programa chamado ListaPessoa defina uma classe Pessoa que possui as propriedades Nome e SobreNome. (Note que a classe deve ter um construtor vazio para que o XAML possa criar as instâncias).
Para definir a classe Pessoa selecione o menu Project -> Add Class e informe o nome Pessoa.vb para o arquivo da classe. O código da classe Pessoa é visto a seguir:
Public Class Pessoa Private _nome As String Private _sobrenome As String Public Property Nome() As String Get Return _nome End Get Set(ByVal Value As String) _nome = Value End Set End Property Public Property SobreNome() As String Get Return _sobrenome End Get Set(ByVal Value As String) _sobrenome = Value End Set End Property End Class |
Obs: Essa classe será usada nos demais exemplos quando necessário.
A seguinte declaração de namespace no interior do elemento Window permite que o código XAML refere-se a classe Pessoa e outras classes definidas no programa.
xmlns:local="clr-namespace:DataBinding_Cenarios"
Agora podemos definir na declaração XAML o objeto Pessoa :
<Window.Resources>
<local:Pessoa
x:Key="porAuthor" Nome="Jose Carlos"
SobreNome="Macoratti"/>
</Window.Resources>
A seguir o código XAML a seguir realiza a vinculação com as propriedades do Objeto :
<Label
Content="{Binding Source={StaticResource porAuthor},
Path=Nome}"/>
<Label Content="{Binding Source={StaticResource
porAuthor}, Path=SobreNome}"/>
O código completo pode ser visto abaixo:
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DataBinding_Cenarios" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <local:Pessoa x:Key="porAuthor" Nome="Jose Carlos" SobreNome="Macoratti"/> </Window.Resources> <Grid> <StackPanel> <Label Content="{Binding Source={StaticResource porAuthor}, Path=Nome}"/> <Label Content="{Binding Source={StaticResource porAuthor}, Path=SobreNome}"/> </StackPanel> </Grid> </Window> |
Você pode exibir o nome completo sobre-escrevendo o método ToString() na classe Pessoa.
Public Overrides Function ToString() As String Return Nome + " " + SobreNome End Function |
Agora se o código XAML refere-se ao objeto sem um parâmetro Path, a vinculação retorna o valor padrão do objeto, o qual é a string retornada pelo método ToString.
<Label Content="{Binding Source={StaticResource porAuthor}}" />
Abaixo vemos o código completo e o resultado:
<Window x:Class="MainWindow" Name="MacWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DataBinding_Cenarios" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <local:Pessoa x:Key="porAuthor" Nome="Jose Carlos" SobreNome="Macoratti"/> </Window.Resources> <Grid> <StackPanel> <Label Content="{Binding Source={StaticResource porAuthor}, Path=Nome}"/> <Label Content="{Binding Source={StaticResource porAuthor}, Path=SobreNome}"/> <Label Content="{Binding Source={StaticResource porAuthor}}" /> </StackPanel> </Grid> </Window> |
3- Binding com classes em XAML
Veremos agora um cenário onde o código se vincula a um objeto Pessoa que é criado no code-behind.
Suponha que o programa defina uma classe Pessoa com as propriedades Nome e SobreNome e um método ToString sobrescrito conforme descrito no item anterior.
Agora suponha que você queira criar via code-behind um objeto Pessoa depois realizar a vinculação via código XAML com esse objeto.
Adicione no code-behind o código a seguir para criar o objeto e a propriedade que retorna o objeto semelhante:
Class MainWindow Private m_Pessoa As New Pessoa() With { _ .Nome = "Jose Carlos", .SobreNome = "Macoratti"} Public Property Mac_Pessoa() As Pessoa Get Return m_Pessoa End Get Set(ByVal value As Pessoa) m_Pessoa = value End Set End Property End Class |
No código XAML inclua a declaração : xmlns:local="clr-namespace:DataBinding_Cenarios"
Observe que o elemento principal Window também especifica o nome da janela usando um atributo Name ou um x:Name. No nosso caso : Name="MacWindows"
Agora o código XAML pode usar esse nome para se referir ao elemento da janela que está executando o código. Pode então referir-se a propriedade da janela que retorna o objeto Pessoa.
O código a seguir vincula um Label ao objeto retornado pela propriedade Mac_Pessoa da janela Window.
<Window x:Class="MainWindow" Name="MacWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DataBinding_Cenarios" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <local:Pessoa x:Key="porAuthor" Nome="Jose Carlos" SobreNome="Macoratti"/> </Window.Resources> <Grid> <StackPanel> <Label Content="{Binding ElementName=MacWindow, Path=Mac_Pessoa}"/> <Label Content="{Binding ElementName=MacWindow, Path=Mac_Pessoa.Nome}"/> </StackPanel> </Grid> </Window> |
4- Tratando com coleções de dados
Como os controles de itens como ListBox, ComboBox e TreeView exibem grupos de itens os dados a eles vinculados devem conter grupos de valores.
Veremos a seguir como vincular coleções de dados a esses controles no código XAML e no code-behind.
1- VInculando coleções via XAML
Para vincular uma coleção de dados usando o código XAML defina a seguinte declaração XAML : xmlns:sys=clr-namespace:System;assembly=mscorlib
Agora podemos usar um elemento x:Array para criar um array de objetos que usa os tipos de dados do sistema. O código a seguir define um array de string chamado nomes:
<Window.Resources> <x:Array x:Key="nomes" Type="sys:String"> <sys:String>Macoratti</sys:String> <sys:String>Miriam</sys:String> <sys:String>Janice</sys:String> <sys:String>Jefferson</sys:String> <sys:String>Jessica</sys:String> </x:Array> </Window.Resources> |
Agora podemos vincular o array a um controle de itens. No exemplo abaixo estamos usando um controle ListBox:
<Window x:Class="MainWindow" Name="MacWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DataBinding_Cenarios" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <x:Array x:Key="nomes" Type="sys:String"> <sys:String>Macoratti</sys:String> <sys:String>Miriam</sys:String> <sys:String>Janice</sys:String> <sys:String>Jefferson</sys:String> <sys:String>Jessica</sys:String> </x:Array> </Window.Resources> <Grid> <StackPanel> <ListBox ItemsSource="{StaticResource nomes}"/> </StackPanel> </Grid> </Window> |
2- VInculando coleções via Code-behind
Veremos agora um cenário onde o código se vincula a uma coleção de objetos Pessoa que é criado no code-behind.
Suponha que o programa defina uma classe Pessoa com as propriedades Nome e SobreNome e um método ToString sobrescrito conforme descrito no item anterior.
Agora suponha que você queira criar via code-behind uma coleção de objetos Pessoa e depois realizar a vinculação via código XAML com um controle ListBox.
No code-behind inclua o código abaixo para criar um array e uma propriedade que retorna o array. Ele define um array de objetos Pessoa e a propriedade Mac_Pessoa que retorna o array.
Private m_Pessoa As Pessoa() = New Pessoa() {New Pessoa() With { _ .Nome = "Jose Carlos", _ .SobreNome = "Macoratti" _ }, New Pessoa() With { _ .Nome = "Jefferson", _ .SobreNome = "Andre" _ }, New Pessoa() With { _ .Nome = "Janice", _ .SobreNome = "Rachel" _ }, New Pessoa() With { _ .Nome = "Miriam", _ .SobreNome = "Estela" _ }} Public Property Mac_Pessoa() As Pessoa() Get Return m_Pessoa End Get Set(ByVal value As Pessoa()) m_Pessoa = value End Set End Property |
No código XAML inclua a declaração : xmlns:local="clr-namespace:DataBinding_Cenarios"
Observe que o elemento principal Window também especifica o nome da janela usando um atributo Name ou um x:Name. No nosso caso : Name="MacWindows"
Agora o código XAML pode usar esse nome para se referir ao elemento da janela que está executando o código. Pode então referir-se a propriedade da janela que retorna o objeto Pessoa.
A seguir temos o código XAML que vincula o ListBox a propriedade Mac_Pessoa que retorna a coleção de objetos Pessoa:
<Window x:Class="MainWindow" Name="MacWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DataBinding_Cenarios" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="MainWindow" Height="350" Width="525"> <Grid> <StackPanel> <ListBox ItemsSource="{Binding ElementName=MacWindow, Path=Mac_Pessoa}"/> </StackPanel> </Grid> </Window> |
Nota: A vinculação aos demais controles de itens segue o mesmo procedimento. Para ilustrar vemos abaixo a mesma vinculação com um controle ComboBox:
<Window x:Class="MainWindow" Name="MacWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DataBinding_Cenarios" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="MainWindow" Height="350" Width="525"> <Grid> <StackPanel> <ComboBox ItemsSource="{Binding ElementName=MacWindow, Path=Mac_Pessoa}"/> </StackPanel> </Grid> </Window> |
5 - Usando Templates
Acabamos de mostrar como
criar array de itens e realizar a vinculação usando o controle ListBox e ComboBox. Estes controles permitem também que você
especifique um DataTemplate que determina como o controle irá
exibir cada item. Para fazer isso você tem que realizar 3
tarefas básicas:
1 -
Criar um elemento ItemTemplate;
2 - No interior deste elemento coloque o elemento DataTemplate
contendo os controles que você quer usar para exibir cada item;
3 - Realize a vinculação com data context do controle
desejado;.
No exemplo a seguir vinculamos um ListBox a matriz Mac_Pessoa definida no item anterior onde o DataTemplate faz com que o controle exiba cada item em dois controles TextBlocks separador por um outro controle contendo espaço onde no terceiro controle exibimos o sobrenome em negrito e na cor azul:
<Window x:Class="MainWindow" Name="MacWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DataBinding_Cenarios" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="MainWindow" Height="350" Width="525"> <Grid> <StackPanel> <ListBox ItemsSource="{Binding ElementName=MacWindow, Path=Mac_Pessoa}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Nome}" FontWeight="Normal"/> <TextBlock Text=" "/> <TextBlock Text="{Binding SobreNome}" FontWeight="Bold" ForeGround="Blue"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel> </Grid> </Window> |
Com isso fizemos uma pequena revisão recordando os pontos básicos do databinding no WPF que pode lhe ajudar no seu dia a dia.
Pegue o projeto completo aqui: DataBinding_Cenarios.zip
Eu sei é apenas WPF, mas eu gosto...
"Sendo pois justificados pela fé, temos paz com Deus, por nosso Senhor Jesus Cristo."(Rom:5-1)
Referências:
Apresentando o WPF - Windows Presentation Foundation - Macoratti.net
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#