这可能是一个显而易见的问题,但我认为可能有多种方法可以实现它,所以这不仅对我有用,而且希望它对其他人有用。
基本上我正在寻找实现列表视图的最佳方法,该列表视图可以接受不同类型的对象,然后使用适合该对象的项目/数据模板呈现它们。
例如......我们有一个标准的产品列表视图,当我们查看不同的类别时,业务部门决定为每个不同的类别显示不同的项目模板样式。
在这里提出这个问题的主要原因是避免使用讨厌的hacky解决方案,而是发现一种干净的方法。
希望我已经提供了足够的信息,如果您需要更多信息,请告诉我。
答案 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>
(请注意,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}"
>