Introduction
It is common programming practice to use Enumerations to make code more readable but it also is annoying when saving to database since you always have to convert it back to integer or other type depending on case. This tip is about to use Integer directly instead of using Enum
in XAML.
Background
I'm working in universal App (for Windows and Windows phone) and found it is trivial to work with enumerations on project since, by default, WinRT applications do NOT have direct access to any type of database structure.
I did start using SQLite as an extension, therefore it becomes annoying using enum
, as it requires conversion to native data types.
Using the Code
To put it in an example, first we create a Test Class:
public class ClsTest : System.ComponentModel.INotifyPropertyChanged
{
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([System.Runtime.CompilerServices.CallerMemberName]
String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
private int _iCombo;
public int iCombo
{
get { return _iCombo; }
set { _iCombo = value; NotifyPropertyChanged("iCombo"); }
}
private int _iRadio;
public int iRadio
{
get { return _iRadio; }
set { _iRadio = value; NotifyPropertyChanged("iRadio"); }
}
public ClsTest()
{
}
}
For ComboBox
, we create class to support List
of integer and converter:
public class ComboListInt : List<int>
{
}
public class ConverterComboIntToString : Windows.UI.Xaml.Data.IValueConverter
{
object Windows.UI.Xaml.Data.IValueConverter.Convert
(object value, Type targetType, object parameter, string language)
{
if (value != null)
{
int i = -1;
i = (int)value;
switch (i)
{
case 0:
return "First";
case 1:
return "Second";
case 2:
return "Third";
case 3:
return "Fourth";
}
}
return "";
}
object Windows.UI.Xaml.Data.IValueConverter.ConvertBack
(object value, Type targetType, object parameter, string language)
{
return value;
}
}
For RadioButton
, we create converter:
public class ConverterRadioIsChecked : Windows.UI.Xaml.Data.IValueConverter
{
object Windows.UI.Xaml.Data.IValueConverter.Convert
(object value, Type targetType, object parameter, string language)
{
if (value != null && parameter != null)
{
int i = -1;
int.TryParse(parameter.ToString(), out i);
if ((int)value == i)
{
return true;
}
}
return false;
}
object Windows.UI.Xaml.Data.IValueConverter.ConvertBack
(object value, Type targetType, object parameter, string language)
{
if (value != null && parameter != null)
{
int i = -1;
int.TryParse(parameter.ToString(), out i);
return i;
}
return -1;
}
}
In XAML, we initialize all our classes and converters as static resources
:
<Page.Resources>
-->
<local:ClsTest iCombo="2" iRadio="2" x:key="myTestClass" />
-->
<local:ComboListInt x:key="myComboListInt">
<x:Int32>0</x:Int32>
<x:Int32>1</x:Int32>
<x:Int32>2</x:Int32>
<x:Int32>3</x:Int32>
</local:ComboListInt>
-->
<local:ConverterComboIntToString x:key="myConverterComboIntToString" />
-->
<local:ConverterRadioIsChecked x:key="myConverterRadioIsChecked" />
</Page.Resources>
Put initialized ClsTest
into DataContext
of parent control (e.g.: Page
, Grid
, StackPanel
, etc.) so its properties are available to both ComboBox
and RadioButtons
.
<StackPanel DataContext="{StaticResource myTestClass}">
-->
-->
-->
....
</StackPanel>
XAML for ComboBox
:
<ComboBox ItemsSource="{StaticResource myComboListInt}"
SelectedValue="{Binding Path=iCombo, Mode=TwoWay}">
<ComboBox.TtemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource myConverterComboIntToString}}" />
</DataTemplate>
</ComboBox.TtemTemplate>
</ComboBox>
XAML for RadioButton
(note integers are passed as parameters of converter and descriptions are directly in content):
<RadioButton IsChecked="{Binding Path=iRadio, Converter={StaticResource myConverterRadioIsChecked},
ConverterParameter=0, Mode=TwoWay}">One</RadioButton>
<RadioButton IsChecked="{Binding Path=iRadio, Converter={StaticResource myConverterRadioIsChecked},
ConverterParameter=1, Mode=TwoWay}">Two</RadioButton>
<RadioButton IsChecked="{Binding Path=iRadio, Converter={StaticResource myConverterRadioIsChecked},
ConverterParameter=2, Mode=TwoWay}">Three</RadioButton>
<RadioButton IsChecked="{Binding Path=iRadio, Converter={StaticResource myConverterRadioIsChecked},
ConverterParameter=3, Mode=TwoWay}">Four</RadioButton>
Points of Interest
This can be used to work with globalization setting using language parameter of converters to match proper regional settings:
We could also have created converter to present Content
of radio buttons, e.g.:
public class ConverterRadioIntToString : Windows.UI.Xaml.Data.IValueConverter
{
object Windows.UI.Xaml.Data.IValueConverter.Convert
(object value, Type targetType, object parameter, string language)
{
int i = -1;
if (parameter != null)
{
int.TryParse(parameter.ToString(), out i);
switch (i)
{
case 0:
return "Um one";
case 1:
return "Dois Two";
case 2:
return "Tres Tree";
case 3:
return "Quatro Four";
}
}
return "???";
}
object Windows.UI.Xaml.Data.IValueConverter.ConvertBack
(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
in XAML resources:
<local:ConverterRadioIntToString x:key="myConverterRadioIntToString" />
RadioButton
XAML would be:
<RadioButton Content="{Binding Converter={StaticResource myConverterRadioIntToString},
ConverterParameter=1}"
IsChecked="{Binding Path=iRadio,
Converter={StaticResource myConverterRadioIsChecked},
ConverterParameter=1, Mode=TwoWay}">
</RadioButton>