如何实现自动DataTemplate选择以基于数据类型,就像在items控件中一样?

8
我们正在编写一个非常专业的ItemsControl,每个“行”实际上有三个ContentPresenter,分别绑定到不同的对象(考虑穷人的网格),而不是像ListBox一样使用更常见的一个。

现在,如果您没有明确指定ItemTemplateItemTemplateSelector,则ListBox似乎有一些内部选择器,根据数据类型纯粹应用模板。 但是,我们的ContentPresenter并没有捕获它们。 我们还尝试将它们切换为ContentControl,但也没有起作用。

现在我知道我可以简单地编写自己的DataTypeTemplateSelector来执行此操作,但我想知道是否已经在某个地方“内置”了这个功能,因为它与许多ItemsControlListBoxTreeViewComboBoxDataGrid等)一起使用,并根据此MSDN文章...

http://msdn.microsoft.com/en-us/library/ms742521.aspx

它应该默认就能工作!但是,它并没有。

这是我们的(伪)代码...

<UserControl.Resources>

    <!-- These all work when the relevant items are in a ListBox,
         but not with stand-alone ContentPresenters or ContentControls -->

    <DataTemplate DataType="local:SomeTypeA">
        <TextBlock Text="{Binding Converter={c:DataTypeNameConverter}}" Foreground="Blue" />
    </DataTemplate>

    <DataTemplate DataType="local::SomeTypeB">
        <TextBlock Text="{Binding Converter={c:DataTypeNameConverter}}" Foreground="Purple" />
    </DataTemplate>

    <DataTemplate DataType="local::SomeTypeC">
        <TextBlock Text="{Binding Converter={c:DataTypeNameConverter}}" Foreground="Purple" />
    </DataTemplate>

</UserControl.Resources>

<!-- These don't pick up the templates -->
<ContentControl Content="{Binding Field1}" />
<ContentPresenter Content="{Binding Field2}" />

<!-- This however does -->
<ListBox ItemsSource="{Binding AllItems}" 

那么...有人想尝试一下为什么不行吗?


我以前多次使用过DataTemplatesContentControls,没有遇到任何问题。你能否发布实际代码而不是伪代码?如果将DataType设置为{x:Type local:SomeTypeA}而不仅仅是"local:SomeTypeA",它是否有效? - Rachel
Rachel,你说得对。正如H.B.在下面指出的那样,使用标记扩展x:Type确实可以实现它...微软在其无限的智慧中认为一个名叫“DataType”的属性属于Object类型,而不是System.Type类型,所以与样式的'TargetType'不同,对于DataTemplate,您必须使用标记扩展。 - Mark A. Donohoe
1个回答

8

DataType,无论出于任何疯狂的原因,都是Object类型,因此DataTemplates在该属性中设置了string,除非您使用x:Type


编辑: 属性为对象的设计有非常充分的理由,通常那些会读(并且确实读了)的人显然处于优势位置:

如果模板用于对象数据,则此属性包含数据对象的类型名称(作为字符串)。 若要引用类的类型名称,请使用x:Type标记扩展。 如果模板用于XML数据,则此属性包含XML元素名称。 有关为XML元素指定非默认命名空间的详细信息,请参见文档注释。


啊!原来如此!我太习惯于在样式中省略x:Type来指定TargetType(我假设它已正确设置为类型Type),所以在这里也省略了它,你说类型是Object(你是对的...WTFBBQ,微软?!),结果它被解释为简单字符串,因此永远不会匹配!非常好的发现,特别是因为你知道“为什么!”(我几乎写下这不是必要的,直到我看到你的答案。)不知道这是否应该报告给微软作为一个漏洞!(另外,经验法则:始终使用标记!更清晰且可以正常工作!)再次感谢! - Mark A. Donohoe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接