Hola a todos.
Hoy vamos a ver como hacer un binding en un ComboBox con los valores de un enumerado.
La idea es que usamos el combo con valores de texto, pero después tenemos que convertir al enumerado correspondiente.
Primero vamos a crear una función para convertir el enumerado en un array de elementos Enum.
public Enum[] EnumToArray(Enum enumeration)
//get the enumeration type
Type et = enumeration.GetType();
//get the public static fields (members of the enum)
System.Reflection.FieldInfo[] fi = et.GetFields(BindingFlags.Static | BindingFlags.Public);
//create a new enum array
Enum[] values = new Enum[fi.Length];
//populate with the values
for (int iEnum = 0; iEnum < fi.Length; iEnum++)
{
values[iEnum] = (Enum)fi[iEnum].GetValue(enumeration);
}
//return the array
return values;
}
Luego vamos a crear un enumerado sencillo... Type1, Type2 y Type3 que es el que vamos a utilizar para rellenar el combo box.
Para ello vamos a crear una función en MainPage.xaml.cs invocando a esta función y usando un bucle foreach rellenamos el combo Box.
private void PopulateListBox()
{
Enum2ListViewViewModel viewModel = DataContext as Enum2ListViewViewModel;
if (viewModel != null)
{
Enum[] enumValues = viewModel.EnumToArray(new Enum2ListViewViewModel.MyType());
myListEnum.Items.Clear();
foreach(Enum enums in enumValues)
{
myListEnum.Items.Add(enums.ToString());
// Note that the combo has strings values
// however, we going to update a Enum value
}
}
}
Como dice el comentario, en el combo vamos a poner string, pero vamos a bindearlo contra un enumeado. ¿Donde está la magia?
Pues la magia está en las funciones Converter.
Creamos una clase para convertir el valor, heredando de IValueConverter.
namespace KurroSoftware.Enum2ListView.Converters
{
public class MyTypeEnumToStringConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (Enum2ListViewViewModel.MyType)Enum.Parse(typeof(Enum2ListViewViewModel.MyType), value.ToString(), true);
}
}
}
Como veras, usamos el Enum.Parse para convertir el string en el enumerado del tipo MyType.
Luego en el XAML, hacemos el binding del combo de la siguiente forma
<ComboBox x:Name="myListEnum"
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
SelectedValue="{Binding TypeEnum, Converter={StaticResource MyTypeEnum}, Mode=TwoWay}"
Grid.ColumnSpan="2" />
Como verás, esta accediendo directamente a la property TypeEnum que es del tipo MyEnum, pero usando el Converter, se hace la traducción string-enum.
xmlns:converter="clr-namespace:KurroSoftware.Enum2ListView.Converters"
......
<UserControl.Resources>
<converter:MyTypeEnumToStringConverter x:Key="MyTypeEnum" />
</UserControl.Resources>
Usando este pequeño truco, podemos hacer un binding directamente con el content.
Para rizar el rizo, y como estoy acostumbrado a la metodología de MVVM (Model-View-ViewModel), he usado la clase CommandDelegate para que la lógica del botón que está en la vista, esté siendo ejecutada en el ViewModel, en lugar del View.
Esto es sencillo usando el patrón Prism (ver http://msdn.microsoft.com/es-es/magazine/dd943055.aspx ), pero por no tener que usar todas las librerías de este patrón, he usado el CommandDelegate que publicó Kunal Chowdhury en CodeProject, (ver Step by Step Guide to Silverlight 4 Command Binding )
Bueno, pues ya sabes, el código en el siguiente enlace.
Enum2ComboBox.zip
Espero tus comentarios.
Hoy vamos a ver como hacer un binding en un ComboBox con los valores de un enumerado.
La idea es que usamos el combo con valores de texto, pero después tenemos que convertir al enumerado correspondiente.
Primero vamos a crear una función para convertir el enumerado en un array de elementos Enum.
public Enum[] EnumToArray(Enum enumeration)
//get the enumeration type
Type et = enumeration.GetType();
//get the public static fields (members of the enum)
System.Reflection.FieldInfo[] fi = et.GetFields(BindingFlags.Static | BindingFlags.Public);
//create a new enum array
Enum[] values = new Enum[fi.Length];
//populate with the values
for (int iEnum = 0; iEnum < fi.Length; iEnum++)
{
values[iEnum] = (Enum)fi[iEnum].GetValue(enumeration);
}
//return the array
return values;
}
Luego vamos a crear un enumerado sencillo... Type1, Type2 y Type3 que es el que vamos a utilizar para rellenar el combo box.
Para ello vamos a crear una función en MainPage.xaml.cs invocando a esta función y usando un bucle foreach rellenamos el combo Box.
private void PopulateListBox()
{
Enum2ListViewViewModel viewModel = DataContext as Enum2ListViewViewModel;
if (viewModel != null)
{
Enum[] enumValues = viewModel.EnumToArray(new Enum2ListViewViewModel.MyType());
myListEnum.Items.Clear();
foreach(Enum enums in enumValues)
{
myListEnum.Items.Add(enums.ToString());
// Note that the combo has strings values
// however, we going to update a Enum value
}
}
}
Como dice el comentario, en el combo vamos a poner string, pero vamos a bindearlo contra un enumeado. ¿Donde está la magia?
Pues la magia está en las funciones Converter.
Creamos una clase para convertir el valor, heredando de IValueConverter.
namespace KurroSoftware.Enum2ListView.Converters
{
public class MyTypeEnumToStringConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (Enum2ListViewViewModel.MyType)Enum.Parse(typeof(Enum2ListViewViewModel.MyType), value.ToString(), true);
}
}
}
Como veras, usamos el Enum.Parse para convertir el string en el enumerado del tipo MyType.
Luego en el XAML, hacemos el binding del combo de la siguiente forma
<ComboBox x:Name="myListEnum"
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
SelectedValue="{Binding TypeEnum, Converter={StaticResource MyTypeEnum}, Mode=TwoWay}"
Grid.ColumnSpan="2" />
Como verás, esta accediendo directamente a la property TypeEnum que es del tipo MyEnum, pero usando el Converter, se hace la traducción string-enum.
xmlns:converter="clr-namespace:KurroSoftware.Enum2ListView.Converters"
......
<UserControl.Resources>
<converter:MyTypeEnumToStringConverter x:Key="MyTypeEnum" />
</UserControl.Resources>
Usando este pequeño truco, podemos hacer un binding directamente con el content.
Para rizar el rizo, y como estoy acostumbrado a la metodología de MVVM (Model-View-ViewModel), he usado la clase CommandDelegate para que la lógica del botón que está en la vista, esté siendo ejecutada en el ViewModel, en lugar del View.
Esto es sencillo usando el patrón Prism (ver http://msdn.microsoft.com/es-es/magazine/dd943055.aspx ), pero por no tener que usar todas las librerías de este patrón, he usado el CommandDelegate que publicó Kunal Chowdhury en CodeProject, (ver Step by Step Guide to Silverlight 4 Command Binding )
Bueno, pues ya sabes, el código en el siguiente enlace.
Enum2ComboBox.zip
Espero tus comentarios.
Thanks Kurro realy good stuff
ResponderEliminar