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 of Model objects which I would like to convert to their ViewModel representations but in this scenario,
<ListBox ItemsSource="{Binding ModelItems,
Converter={StaticResource ModelToViewModelConverter}" />
the converter would be written to convert the whole collection ModelItems
at once.
I wish to convert the items of the collection individually, is there a way to do that? I might want to use a CollectionViewSource
and have some filtering logic so I don't want to have to iterate over the whole collection every time something changes.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With