In WPF you can use an IValueConverter or IMultiValueConverter to convert a data-bound value from say an int
to a Color.
I have a collection
Yes you can. It is acting the same as with the IValueConverter. You simply treat the value parameter for the Convert method as a collection.
Here is an example of Converter for a collection:
public class DataConvert : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ObservableCollection<int> convertible = null;
var result = value as ObservableCollection<string>;
if (result != null)
{
convertible = new ObservableCollection<int>();
foreach (var item in result)
{
if (item == "first")
{
convertible.Add(1);
}
else if (item == "second")
{
convertible.Add(2);
}
else if (item == "third")
{
convertible.Add(3);
}
}
}
return convertible;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
In this case is just a proof of concept, but I think it should show the idea very well. The Converter converts from a simple collection of strings like this:
ModelItems = new ObservableCollection<string>();
ModelItems.Add("third");
ModelItems.Add("first");
ModelItems.Add("second");
into a collection of integers corresponding to the string meaning.
And here is the corresponding XAML (loc is the reference of the current assembly where is the converter):
<Window.Resources>
<loc:DataConvert x:Key="DataConverter"/>
</Window.Resources>
<Grid x:Name="MainGrid">
<ListBox ItemsSource="{Binding ModelItems, Converter={StaticResource DataConverter}}"/>
</Grid>
If you want to make a two way binding, you have to implement also the convert back. From the experience of working with MVVM, i suggest to use something like the Factory Pattern to transform from Model in ViewModel and backwards.
Here is another example. I'm using MVVM Caliburn Micro. MyObjects is a list of enums in my case.
<ListBox x:Name="MyObjects">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ., Converter={StaticResource MyConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You cannot set the converter on the collection itself, because it would get the collection as input. You have two choices:
If you want to use the second approach, then use something like this:
<ListBox ItemsSource="{Binding ModelItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Converter={StaticResource ModelToViewModelConverter}}"
ContentTemplate="{StaticResource MyOptionalDataTemplate}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If you don't need a custom datatemplate, then you can skip the ContentTemplate attribute.