使用WPF Datatemplates在一个ListBox中显示两个集合中的项目

时间:2012-02-06 10:44:32

标签: wpf datatemplate

我正在尝试创建一个将文本和图像显示为一个项目的列表框。列表框项目具有文本和图像的ID。可以在LINQ表达式中使用图像ID来获取图像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 个答案:

答案 0 :(得分:2)

我认为你有两种方式:

一个。使用绑定转换器通过从第二个列表中查找图像ID来转换图像ID,然后将ListBox绑定到列表。

B中。创建一个包装类,作为数据的ViewModel,并将ListBox绑定到ViewModel对象。

修改
关于使用值转换器:
如果您可以使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=...}"/>

但是我应该如何从DataContext获取Users属性?在上述两个选项中的任何一个中,您都应该能够将属性绑定到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的{​​{1}}属性同时绑定到PosterID和TextBlock属性,并使用值转换器(IMultiValueConverter)进行转换他们将图像URI。