Olá, pessoal! Veremos neste artigo uma situação um pouco mais técnica, para solucionar
um “problema” que você pode perder algum tempo “garimpando”
a internet para resolver. Veremos como trabalhar com enumerados em um binding de
dados Silverlight.
Criando a aplicação
Crie um projeto Silverlight
Application normal (Visual Studio ( 2008 ou 2010 ) > File >
New > Project > Silverlight Application ==> para facilitar
coloque o nome do projeto como SilverlightApplication1).
Depois de
criar o projeto, crie uma nova classe no projeto Silverlight e nomeie-a
como Pessoa. Em seguida, inclua o seguinte trecho de código:
public enum TipoPessoa <br />{ <br /> Fisica = 0, <br /> Juridica = 1 <br />}<br /><br />public class Pessoa : INotifyPropertyChanged <br />{ <br /> private string _nome; <br /> public string Nome <br /> { <br /> get <br /> { <br /> return _nome; <br /> } <br /> set <br /> { <br /> _nome = value; <br /> OnPropertyChanged("Nome"); <br /> } <br /> } <br /><br /> private TipoPessoa _tipoPessoa; <br /> public TipoPessoa TipoPessoa <br /> { <br /> get { return _tipoPessoa; } <br /> set <br /> { <br /> _tipoPessoa = value; <br /> OnPropertyChanged("TipoPessoa"); <br /> } <br /> } <br /><br /> public event PropertyChangedEventHandler PropertyChanged; <br /><br /> public void OnPropertyChanged(string propertyName) <br /> { <br /> if (PropertyChanged != null) <br /> PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); <br /> } <br />} A código é bem
simples, tem apenas um Enumerado e uma classe Pessoa que possui 2 propriedades,
Nome e TipoPessoa, e contém uma implementação básica da interface
INotifyPropertyChanged. Até aí, tudo bem.
Agora, abra o arquivo
MainPage.xaml e crie 2 linhas no grid LayoutRoot; inclua um data grid
na linha 0, e um StackPanel contendo um TextBlock e um ComboBox na linha
1, conforme o código abaixo:
<Grid x:Name="LayoutRoot" Background="White"> <br /> <Grid.RowDefinitions> <br /> <RowDefinition /> <br /> <RowDefinition /> <br /> </Grid.RowDefinitions> <br /><br /> <sdk:DataGrid AutoGenerateColumns="False" Height="150" HorizontalAlignment="Left" Name="dataGrid1" VerticalAlignment="Top" Width="327"> <br /> <sdk:DataGrid.Columns> <br /> <sdk:DataGridTextColumn Header="Nome" Binding="{Binding Nome}" /> <br /> <sdk:DataGridTextColumn Header="Tipo Pessoa" Binding="{Binding TipoPessoa,}" /> <br /> </sdk:DataGrid.Columns> <br /> </sdk:DataGrid> <br /><br /> <StackPanel Grid.Row="1" Name="stackPanel1" Width="290" DataContext="{Binding ElementName=dataGrid1, Path=SelectedItem}"> <br /><br /> <TextBox Height="23" HorizontalAlignment="Left" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Nome}" /> <br /><br /><ComboBox x:Name="cboTipoPessoa" <br /> ItemsSource="{Binding TipoPessoa}" SelectedIndex="{Binding TipoPessoa}"/> <br /><br /> </StackPanel> <br /></Grid> * não esqueça de adicionar o
namespace do data grid ( xmlns:sdk=”http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk” ) para facilitar arraste
o DataGrid a partir da ToolBox.
Agora que temos nossa
tela praticamente funcionando, abra o arquivo MainPage.xamls.cs e crie
uma lista de dados que será o nosso ItemsSource do DataGrid; verifique
o código abaixo:
public MainPage() <br />{ <br /> InitializeComponent(); <br /> ListaPessoas = new ObservableCollection<Pessoa>(); <br /><br /> ListaPessoas.Add(new Pessoa() { Nome = "Djonatas Tenfen", TipoPessoa = TipoPessoa.Fisica }); <br /> ListaPessoas.Add(new Pessoa() { Nome = "CodeTec Solutions", TipoPessoa = TipoPessoa.Juridica }); <br /> ListaPessoas.Add(new Pessoa() { Nome = "Silverlight Brasil", TipoPessoa = TipoPessoa.Juridica }); <br /> ListaPessoas.Add(new Pessoa() { Nome = "João da Silva ", TipoPessoa = TipoPessoa.Fisica }); <br /><br /> dataGrid1.ItemsSource = ListaPessoas; <br /><br />}<br /><br />public ObservableCollection<Pessoa> ListaPessoas { get; set; }Observe que criei uma propriedade ObservableCollection<Pessoa> ( lembre-se de adicionar
o using System.Collections.ObjectModel; ), que será a lista de dados
para preencher o DataGrid da MainPage. No próprio construtor da classe
eu criei a lista e incluí algumas pessoas do tipo Física e Jurídica e as determinei como ItemsSource do DataGrid, agora vamos executar
e ver o problema.

Problema
Observe que os valores
do enumerado apareceram corretamente no DataGrid, porém no ComboBox,
não?
Solução
Uma solução para isso
será trabalhar com Converter. O que seria isso? Como o próprio
nome já diz, serve para converter valores que são implementações
da interface IValueConverter.
Vamos precisar converter um enumerado
em uma lista de dados para que seja consumido pelo ComboBox. Veja abaixo
a codificação dos converter:
Crie uma pasta na sua
aplicação e dê o nome de Converter (não é obrigatório, mas é melhor manter uma organização dos tipos
de códigos que estamos consumindo; melhor mesmo
é criar um Silverlight Library de
Helpers e Converters e consumi-la em projetos distintos).
Crie
uma classe dentro da pasta e nomeie a classe como
EnumToIntConverter.cs, em seguida inclua o seguinte trecho de código:
public class EnumToIntConverter : IValueConverter <br />{ <br /> public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) <br /> { <br /> return (int)value; <br /> } <br /><br /> public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) <br /> { <br /> return Enum.Parse(targetType, value.ToString(), true); <br /> } <br />} <br />public class EnumToIEnumerableConverter : IValueConverter <br />{ <br /> private Dictionary<Type, List<object>> cache = new Dictionary<Type, List<object>>(); <br /><br />public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) <br /> { <br /> var type = value.GetType(); <br /> if (!this.cache.ContainsKey(type)) <br /> { <br /> var fields = type.GetFields().Where(field => field.IsLiteral); <br /> var values = new List<object>(); <br /> foreach (var field in fields) <br /> { <br /> DescriptionAttribute[] a = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), false); <br /> if (a != null && a.Length > 0) <br /> values.Add(a[0].Description); <br /> else <br /> values.Add(field.GetValue(value)); <br /> } <br /> this.cache[type] = values; <br /> } <br /><br /> return this.cache[type]; <br /> } <br /><br /> public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) <br /> { <br /> throw new NotImplementedException(); <br /> } <br />} Observe que há duas classes
neste código, EnumToIntConverter e EnumToIEnumerableConverter, que servem
para converter o Enumerado em uma lista de dados e converter o item
selecionado da lista em um enumerado. O legal disso tudo é que ela
pode ser usada para qualquer enumerado.
Resolvendo
Agora que já temos
a solução do problema, vamos implementar.
Abra o arquivo MainPage.xaml
e inclua o seguinte namespace: xmlns:local=”clr-namespace:SilverlightApplication1.Converter”. Confira se o namespace confere com o namespace das classes EnumToIEnumerableConverter
e EnumToIntConverter que criamos anteriormente.
Agora vamos adicionar
um resource no XAML para que possamos consumí-las. Logo após a declaração
dos namespace (cabeçalho do arquivo
MainPage.xaml) inclua o seguinte trecho de código:
<UserControl.Resources> <br /> <ResourceDictionary> <br /> <local:EnumToIEnumerableConverter x:Key="EnumToIEnumerableConverter" /> <br /> <local:EnumToIntConverter x:Key="EnumToIntConverter" /> <br /> </ResourceDictionary> <br /></UserControl.Resources>Observe que estou consumindo
o alias local, que está apontando para o namespace SilverlightApplication1.Converter. Indiquei uma chave para cada classe e agora vamos substituir o código
XAML do ComboBox para que ele consuma esses Resources e, consequentemente,
consuma o converter.
Substitua o código
do ComboBox pelo seguinte código:
<ComboBox x:Name="cboTipoPessoa" <br /> ItemsSource="{Binding TipoPessoa, Mode=OneTime, Converter={StaticResource EnumToIEnumerableConverter}}" <br /> SelectedIndex="{Binding TipoPessoa, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}" />Observe que agora temos
uma propriedade “nova” no Binding: o Converter que consome
um Static Resource, que é a chave para a classe Converter, que irá converter
o Enum em uma lista para setar no ItemsSource do ComboBox, e irá converter
o SelectedIndex em um enumerado para setar na propriedade da classe.
Vejam o resultado:

O código fonte deste
artigo está disponível aqui: EnumSilverlight31082010.zip
Não deixem
de comentar! Se alguém tiver outra maneira de fazer a mesma coisa, compartilhe!







