WPF中的条件列表itemtemplate或datatemplate

时间:2011-04-13 04:25:42

标签: wpf view

这可能是一个显而易见的问题,但我认为可能有多种方法可以实现它,所以这不仅对我有用,而且希望它对其他人有用。

基本上我正在寻找实现列表视图的最佳方法,该列表视图可以接受不同类型的对象,然后使用适合该对象的项目/数据模板呈现它们。

例如......我们有一个标准的产品列表视图,当我们查看不同的类别时,业务部门决定为每个不同的类别显示不同的项目模板样式。

在这里提出这个问题的主要原因是避免使用讨厌的hacky解决方案,而是发现一种干净的方法。

希望我已经提供了足够的信息,如果您需要更多信息,请告诉我。

2 个答案:

答案 0 :(得分:32)

只需在DataTemplates中使用相应的DataType指定Resources即可,例如

<ListView ItemsSource="{Binding Data}">
    <ListView.Resources>
        <!-- Do NOT set the x:Key -->
        <DataTemplate DataType="{x:Type local:Employee}">
            <TextBlock Text="{Binding Name}" Foreground="Blue"/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:Machine}">
            <TextBlock Text="{Binding Model}" Foreground="Red"/>
        </DataTemplate>
    </ListView.Resources>
</ListView>

Screenshot

(请注意,DataTemplate.DataType也可用于隐式XML数据模板化(请参阅文档),因此该属性的属性类型为 System.Type,因此与Style.TargetType不同,您必须使用x:Type来引用CLR类型。如果您只输入一个字符串,则不会将其转换为类型。)

您可能还想查看CompositeCollections,以获得各种类型的干净合并列表。


我使用的示例数据:

ObservableCollection<Employee> data = new ObservableCollection<Employee>(new Employee[]
{
    new Employee("Hans", "Programmer")      ,
    new Employee("Elister", "Programmer")   ,
    new Employee("Steve", "GUI Designer")   ,
    new Employee("Stephen", "GUI Designer") ,
    new Employee("Joe", "Coffee Getter")    ,
    new Employee("Julien", "Programmer")    ,
    new Employee("John", "Coffee Getter")   ,
});
ObservableCollection<Machine> data2 = new ObservableCollection<Machine>(new Machine[]
{
    new Machine("XI2",    String.Empty),
    new Machine("MK2-xx", String.Empty),
    new Machine("A2-B16", String.Empty),
});
CompositeCollection cc1 = new CompositeCollection();
cc1.Add(new CollectionContainer() { Collection = data });
cc1.Add(new CollectionContainer() { Collection = data2 });
Data = cc1;

答案 1 :(得分:11)

一种选择是在代码中创建DataTemplateSelector

public class QueueDisplayDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
    {

        var listBoxItem = item as JobQueueListBoxItem;
        var resourceName = String.Empty;
        switch (listBoxItem.JobQueueListBoxItemType)
        {
            case JobQueueListBoxItemType.QueuedJob :
                resourceName = "DataTemplateQueuedJob";
                break;
            case JobQueueListBoxItemType.TransferWorker :
                resourceName = "DataTemplateTransferWorker";
                break;
            default:
                throw new InvalidOperationException(string.Format("There is no corresponding list box template for {0}", listBoxItem.JobQueueListBoxItemType));
        }
        var element = container as FrameworkElement;
        return element.FindResource(resourceName) as DataTemplate;
    }
}

然后,这将在您的XAML中声明为资源

        <ResourceDictionary>
            <local:QueueDisplayDataTemplateSelector x:Key="QueueDisplayDataTemplateSelector" />

然后你会把它分配给你的列表框:

    <ListBox ItemsSource="{Binding ListBoxContents}" 
             ItemTemplateSelector="{StaticResource QueueDisplayDataTemplateSelector}"
             >