How do I use a ItemTemplateSelector together with a HeaderTemplate in a WPF ListView?

Pascal picture Pascal · Apr 4, 2012 · Viewed 11.9k times · Source

Suppose the following XAML defined window:

<Window x:Class="LayoutTests.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:LayoutTests"
        Title="Window1">
  <Window.Resources>
    <XmlDataProvider x:Key="XmlData" IsInitialLoadEnabled="True">
      <x:XData>
        <Items xmlns="">
          <Item text="Item 1" type="A" />
          <Item text="Item 2" type="B" />
          <Item text="Item 3" type="A" />
        </Items>
      </x:XData>
    </XmlDataProvider>
    <DataTemplate x:Key="TypeATemplate">
      <TextBlock Text="{Binding XPath=./@text}" Foreground="Red"/>
    </DataTemplate>
    <DataTemplate x:Key="TypeBTemplate">
      <TextBlock Text="{Binding XPath=./@text}" Foreground="Green"/>
    </DataTemplate>
    <DataTemplate x:Key="HeaderTemplate">
      <TextBlock Text="A Header"/>
    </DataTemplate>
    <local:TypeSelector x:Key="TypeSelector" TypeATemplate="{StaticResource TypeATemplate}" TypeBTemplate="{StaticResource TypeBTemplate}"/>
  </Window.Resources>
    <Grid>
    <ListView ItemsSource="{Binding Source={StaticResource XmlData}, XPath='/Items/Item'}" ItemTemplateSelector="{StaticResource TypeSelector}">
      <!--<ListView.View>
        <GridView>
          <GridViewColumn Width="Auto" HeaderTemplate="{StaticResource HeaderTemplate}"/>
        </GridView>
      </ListView.View>-->
    </ListView>
  </Grid>
</Window>

And a DataTemplateSelector defined in the code behind like this:

  public class TypeSelector : DataTemplateSelector
  {
    public DataTemplate TypeATemplate { get; set; }
    public DataTemplate TypeBTemplate { get; set; }
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
      var element = item as XmlElement;
      if (element.Attributes["type"].Value == "A")
        return TypeATemplate;
      else
        return TypeBTemplate;
    }
  }

If the code for the header template is not commented out, the DataTypeSelector is not called anymore. How do I specify a DataTemplateSelector and HeaderTemplate at the same time?

Answer

SvenG picture SvenG · Apr 4, 2012

I think what you are trying to do is style a single GridViewColumn and its Header. So move the TemplateSelector from the ListView to the GridViewColumn definition:

<Grid>
  <ListView ItemsSource="{Binding Source={StaticResource XmlData}, XPath='/Items/Item'}">
  <ListView.View>
    <GridView>
      <GridViewColumn Width="Auto" CellTemplateSelector="{StaticResource TypeSelector}" HeaderTemplate="{StaticResource HeaderTemplate}"/>
    </GridView>
  </ListView.View>
  </ListView>
</Grid>