Conditional List itemtemplate or datatemplate in WPF Conditional List itemtemplate or datatemplate in WPF wpf wpf

Conditional List itemtemplate or datatemplate in WPF


Just specifying DataTemplates in the Resources with the respective DataType is enough, e.g.

<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

(Note that DataTemplate.DataType can also be used for implicit XML data templating (see docs), the property type for that reason is not System.Type, so unlike in Style.TargetType you have to use x:Type to reference a CLR-type. If you just enter a string it will not be converted to a type.)

You might also want to look into CompositeCollections, to get clean merged lists of varying types.


Sample data i used:

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;


One option is to create a DataTemplateSelector in your code:

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;    }}

This would then be declared in your XAML as a resource

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

And then you would assign this to you list box:

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