Есть ли способ преобразовать членов коллекции, используемых в качестве источника данных?
В WPF вы можете использовать преобразователь IValueConverter или IMultiValueConverter для преобразования привязанного к данным значения от, скажем, от int
до Color.
У меня есть набор объектов Model, которые я хотел бы преобразовать в их представления ViewModel, но в этом случае
<ListBox ItemsSource="{Binding ModelItems,
Converter={StaticResource ModelToViewModelConverter}" />
конвертер будет записан для преобразования всей коллекции ModelItems
сразу.
Я хочу преобразовать элементы коллекции отдельно, есть ли способ сделать это?
Ответы
Ответ 1
Вы не можете установить конвертер в самой коллекции, потому что он получит коллекцию в качестве входной информации. У вас есть два варианта:
- Убедитесь, что ваш конвертер также может работать с коллекциями (IEnumerable).
- Используйте конвертер в шаблоне элемента.
Если вы хотите использовать второй подход, используйте следующее:
<ListBox ItemsSource="{Binding ModelItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Converter={StaticResource ModelToViewModelConverter}}"
ContentTemplate="{StaticResource MyOptionalDataTemplate}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Если вам не нужна специальная таблица данных, вы можете пропустить атрибут ContentTemplate.
Ответ 2
Да, вы можете. Он действует так же, как и с IValueConverter. Вы просто обрабатываете параметр value для метода Convert как коллекцию.
Вот пример конвертера для коллекции:
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();
}
}
В этом случае это всего лишь доказательство концепции, но я думаю, что это должно хорошо показать идею.
Конвертер преобразует из простой коллекции строк, например:
ModelItems = new ObservableCollection<string>();
ModelItems.Add("third");
ModelItems.Add("first");
ModelItems.Add("second");
в набор целых чисел, соответствующий значению строки.
И вот соответствующий XAML (loc - это ссылка на текущую сборку, где находится преобразователь):
<Window.Resources>
<loc:DataConvert x:Key="DataConverter"/>
</Window.Resources>
<Grid x:Name="MainGrid">
<ListBox ItemsSource="{Binding ModelItems, Converter={StaticResource DataConverter}}"/>
</Grid>
Если вы хотите сделать двустороннюю привязку, вам нужно также реализовать преобразование. Из опыта работы с MVVM я предлагаю использовать что-то вроде шаблона Factory для преобразования из модели в ViewModel и обратно.
Ответ 3
Вот еще один пример. Я использую MVVM Caliburn Micro. MyObjects - это список перечислений в моем случае.
<ListBox x:Name="MyObjects">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ., Converter={StaticResource MyConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>