在 ItemsControl 的 ItemTempate 中使用 ContentTemplateSelector 的 ContentPresenter

问题描述

所以,我有一个带有 ItemTemplate 的 ItemsControl 来可视化它的 ItemsSource 中的项目。 这个模板是一个数据模板,里面有一些控件。

  <ItemsControl ItemsSource="{Binding Items}">
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <TextBlock/>
          <TextBlock/>
          <!-- Content depending on item type -->
          <ContentPresenter Content="{Binding}" ContentTemplateSelector="{StaticResource TemplateSelector}"/>
         <TextBlock/>
        </DataTemplate>
      </ItemsControl.ItemTemplate>
   </ItemsControl>

ItemsSource 中的项目可以是不同的类型。不同类型的大多数属性是相同的,但有些属性是不同的。所以我想将公共内容直接放在 DataTemplate 中,但对于不同的内容,我想要某种仅显示特定类型内容的占位符。

所以我尝试了一个带有 ContentTemplateSelector 的 ContentPresenter。但这不起作用。当我设置内容时,从不调用 TemplateSelector 并显示底层视图模型的名称。当我没有设置Content时,调用了TemplateSelector,但是SelectTemplate函数中的item为null。

我不想为每个 DataType 制作整个 DataTemplate,因为大部分内容都是相同的,而且我会有很多重复的代码

解决方法

您不需要 DataTemplateSelector。

在ItemsControl的Resources中设置不同DataTemplates的DataType即可。 DataTemplates 将根据项目的类型自动选择。

<ItemsControl ItemsSource="{Binding Items}">
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type local:Item1}">
            <TextBlock Text="{Binding Item1Property}"/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:Item2}">
            <TextBlock Text="{Binding Item2Property}"/>
        </DataTemplate>
    </ItemsControl.Resources>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock ... />
                <ContentPresenter Content="{Binding}"/>
                <TextBlock ... />
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>