Отображение элементов из двух коллекций в одном ListBox с использованием шаблонов данных WPF - PullRequest
0 голосов
/ 06 февраля 2012

Я пытаюсь создать список, который отображает текст и изображение как один элемент. Элементы списка имеют текст и идентификатор изображения. Идентификатор изображения можно использовать в выражении LINQ для получения контейнера URI изображения.

В принципе, у меня есть два списка. Каждый элемент в первом списке является ключом для извлечения определенного элемента во втором списке. Как я могу получить обе части данных для отображения в одном списке?

РЕДАКТИРОВАТЬ ДЛЯ ЯРКОСТИ:

первый список представляет собой набор объектов сообщений - ObservableCollection:

class Message
{
    public String PosterID { get; set; }
    public String Text { get; set; } //this isn't important, it is the message body
}

Второй список представляет собой набор профилей пользователей - ObservableCollection:

class User
{
    public String UserID { get; set; }
    public String ProfilePictureURI { get; set; }
}

Чтобы получить данные профиля автора сообщения, вы должны взять «Message.PosterID» и использовать его в качестве «ключа» для соответствия «User.UserID».

Рассматриваемый список в настоящее время связан с ViewModel.Messages. В шаблоне данных списка я успешно распечатываю «Message.Text», НО мне все еще нужно получить «User.ProfilePictureURI».

Мне рекомендуется использовать ValueConverter для преобразования «Message.PosterID» в «User.UserID». Но чтобы сделать это преобразование, мне нужно передать ViewModel.Users в ValueConverter. В настоящее время я не знаю, как это сделать.

1 Ответ

2 голосов
/ 06 февраля 2012

Я думаю, у вас есть два пути:

A.Используйте конвертер привязок для преобразования идентификатора изображения, найдя идентификатор изображения из второго списка, а затем привяжите свой ListBox к списку.

B.Создайте класс-оболочку, который действует как ViewModel для ваших данных, и привяжите ListBox к объекту ViewModel.

EDIT
Об использовании преобразователя значений:
Если вы моглисделайте список Users статическим или используйте какой-либо механизм внедрения зависимостей для получения списка Users, тогда преобразователь значений может легко выполнить преобразование.
Единственный другой способ - каким-то образом передать список пользователей из ViewModel (DataContext) вконвертер привязок.
Сначала я подумал, что вы можете установить Users для свойства конвертера, например:

<ListBox ItemsSource="{Binding Path=Messages}">
    <ListBox.Resources>
        <c:PosterIDConverter x:Key="pidConverter" Users="..."/>
    </ListBox.Resources>
...

Или передать его как ConverterParameter привязке:

<TextBlock Text="{Binding Path=Text, Converter={StaticResource pidConverter,ResourceKey}, ConverterParameter=...}"/>

Но как мне получить свойство Users из DataContext?В любом из двух приведенных выше вариантов вы должны иметь возможность привязать свойство к Users, например так (неверно):

<c:PosterIDConverter x:Key="pidConverter" Users="{Binding Path=Users"/>

Но PosterIDConverter не является DependencyObject и не поддерживает привязку данных.

Рабочее решение:

Вот то, к чему я наконец пришел.

Ваш класс конвертера:

public class PosterIDConverter : IMultiValueConverter
{
    public object Convert(object[] value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string userId = (string)value[0];
        IEnumerable<User> users= (IEnumerable<User>)value[1];

        var user = users.FirstOrDefault(u => u.UserID == userId);
        if (user != null)
            return user.ProfilePictureURI;
        return null;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Ваш файл xaml (только образец):

<ListBox x:Name="lst" DataContext="{StaticResource vm}" ItemsSource="{Binding Path=Messages}">
    <ListBox.Resources>
        <c:PosterIDConverter x:Key="pidConverter"/>
    </ListBox.Resources>
    <ListBox.ItemTemplate>
        <DataTemplate DataType="{x:Type c:Message}">
            <Border BorderBrush="Blue" BorderThickness="1">
                <StackPanel Orientation="Vertical">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="Message: "/>
                        <TextBlock Text="{Binding Path=Text}"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="URI: "/>
                        <TextBlock>
                            <TextBlock.Text>
                                <MultiBinding Converter="{StaticResource pidConverter}">
                                    <Binding Path="PosterID"/>
                                    <Binding ElementName="lst" Path="DataContext.Users"/>
                                </MultiBinding>
                            </TextBlock.Text>
                        </TextBlock>
                    </StackPanel>
                </StackPanel>
            </Border>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

В этом примере я связал свойство Text TextBlock со свойством PosterID и Users одновременно и использовал преобразователь значений ( IMultiValueConverter ) дляпреобразовать их в URI изображения.

...