Desenvolvimento - Silverlight

Trabalhando com enumerados

Este artigo descreve passo a passo como consumir tipos enumerados em um combobox.

por Djonatas Tenfen



Olá pessoal, o post hoje será um pouco mais técnico e voltado para solucionar um “problema” que você pode perder algum tempo “garimpando” a internet para resolver, então para facilitar a vida de vocês vou mostrar 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 nomeie-a como Pessoa em seguida inclua o seguinte trecho de código:

public enum TipoPessoa
{
Fisica = 0,
Juridica = 1
}

public class Pessoa : INotifyPropertyChanged
{
private string _nome;
public string Nome
{
get
{
return _nome;
}
set
{
_nome = value;
OnPropertyChanged("Nome");
}
}

private TipoPessoa _tipoPessoa;
public TipoPessoa TipoPessoa
{
get { return _tipoPessoa; }
set
{
_tipoPessoa = value;
OnPropertyChanged("TipoPessoa");
}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

A código é bem simples tem apenas um Enumerado e uma classe Pessoa que possui 2 propriedades Nome e TipoPessoa e contem uma implementação básica da interface INotifyPropertyChanged, até ai 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 código abaixo:

<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>

<sdk:DataGrid AutoGenerateColumns="False" Height="150" HorizontalAlignment="Left" Name="dataGrid1" VerticalAlignment="Top" Width="327">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Nome" Binding="{Binding Nome}" />
<sdk:DataGridTextColumn Header="Tipo Pessoa" Binding="{Binding TipoPessoa,}” />
</sdk:DataGrid.Columns>
</sdk:DataGrid>

<StackPanel Grid.Row="1" Name="stackPanel1" Width="290" DataContext="{Binding ElementName=dataGrid1, Path=SelectedItem}">

<TextBox Height="23" HorizontalAlignment="Left" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Nome}" />

<ComboBox x:Name="cboTipoPessoa"
ItemsSource="{Binding TipoPessoa}" SelectedIndex="{Binding TipoPessoa}”/>

</StackPanel>
</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()
{
InitializeComponent();
ListaPessoas = new ObservableCollection<Pessoa>();

ListaPessoas.Add(new Pessoa() { Nome = "Djonatas Tenfen", TipoPessoa = TipoPessoa.Fisica });
ListaPessoas.Add(new Pessoa() { Nome = "CodeTec Solutions", TipoPessoa = TipoPessoa.Juridica });
ListaPessoas.Add(new Pessoa() { Nome = "Silverlight Brasil", TipoPessoa = TipoPessoa.Juridica });
ListaPessoas.Add(new Pessoa() { Nome = "João da Silva ", TipoPessoa = TipoPessoa.Fisica });

dataGrid1.ItemsSource = ListaPessoas;

}

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 inclui algumas pessoas do tipo Física Jurídicas, determinei a mesma 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 a baixo a codificação dos converter:

Crie uma pasta na sua aplicação nome-a como 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 consumir esta em projetos distintos ) e 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
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (int)value;
}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Enum.Parse(targetType, value.ToString(), true);
}
}
public class EnumToIEnumerableConverter : IValueConverter
{
private Dictionary<Type, List<object>> cache = new Dictionary<Type, List<object>>();

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var type = value.GetType();
if (!this.cache.ContainsKey(type))
{
var fields = type.GetFields().Where(field => field.IsLiteral);
var values = new List<object>();
foreach (var field in fields)
{
DescriptionAttribute[] a = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (a != null && a.Length > 0)
values.Add(a[0].Description);
else
values.Add(field.GetValue(value));
}
this.cache[type] = values;
}

return this.cache[type];
}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

Observe que tem 2 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 usado 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 consumi-las, logo após a declaração dos namespace ( cabeçalho do arquivo MainPage.xaml ) inclua o seguinte trecho de código:

<UserControl.Resources>
<ResourceDictionary>
<local:EnumToIEnumerableConverter x:Key="EnumToIEnumerableConverter" />
<local:EnumToIntConverter x:Key="EnumToIntConverter" />
</ResourceDictionary>
</UserControl.Resources>

Observe que estou consumindo o alias local que está apontando para o namespace SilverlightApplication1.Converter, indiquei uma chave para cada classe, 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"
ItemsSource="{Binding TipoPessoa, Mode=OneTime, Converter={StaticResource EnumToIEnumerableConverter}}"
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 Descrição: Smiley de boca aberta

Vejam o resultado :

O Código fonte deste artigo está disponível –> EnumSilverlight31082010.rar

Obrigado. Não deixem de comentar, se alguém tiver outra maneira de fazer a mesma coisa não deixe de compartilhar Descrição: Smiley de boca aberta

Djonatas Tenfen

Djonatas Tenfen - Microsoft Certified Professional, entusiasta Microsoft trabalha com desenvolvimento de software a mais de 6 anos, a 2 anos está se dedicando a plataforma Microsoft Silverlight, C# e Windows Phone 7, sócio da CodeTec Solutions empresa especializada em desenvolvimento e consultoria de aplicações Silverlight.
WebCaster MSDN Microsoft, ministrando várias webcast sobre Silverlight, líder da comunidade Silverlight Brasil, palestrante do TechEd 2010, palestrante em diversos Eventos Microsoft pelo Brasil.
Twitter:
http://twitter.com/djonatastenfen
Blog: http://djonatastenfen.spaces.live.com
Comunidade Silverlight Brasil: http://silverlightbrasil.ning.com