我真的很了解你的问题,这就是我的发现。
Q:为什么只有这三个(String
, TypeExtension
, and StaticExtension
) 被允许?
A:通过设计。如果您可以编写任何自定义标记扩展来用作字典中的键,这会带来什么副作用?考虑您将 Binding 作为 DataType 的值...我很确定您可以添加与字典键动态性质相关的许多问题。
Q:此时 XAML 的处理有何特别之处?
A。此时您已创建 BAML。问题来自内部类BamlRecordWriter
,但该消息并未描述实际问题。当您指定自定义标记扩展作为 DataType 时,它采用 DataTemplate 的child,并检查它是否可以从 string、TypeExtension 或 StaticExtension 分配(请参阅BamlRecordWriter.WriteElementStart()功能)。的确。不是您的扩展(可分配给 TypeExtension),而是第一个子扩展(不可分配)。现在你有这个奇怪的“不能是类型虽然它看起来像 BamlRecordWriter 的 bug,但我认为他们是故意留下的。除非它不允许您使用自定义标记扩展作为 DataType 值,否则谁会关心错误消息呢?
Q:是否有另一种方法可以实现此目的(基于可能可为空的类型选择数据模板),而无需求助于 DataTemplateSelector?
A:是的,有点。首先,您可以让标准 TypeExtension 为您完成所有脏活:
<DataTemplate DataType="{x:Type TypeName=System:Nullable`1[[System.Int32]]}">
</DataTemplate>
但在大多数情况下(如果不是总是)您将看不到模板结果。为什么?现在涉及可为空类型的装箱规则。对非 null 可为 null 的值类型进行装箱是对值类型本身进行装箱,而不是对包装该值类型的 System.Nullable 进行装箱。因此,默认模板选择器将查找 DataTemplate 的 DataType 为T
not of Nullable<T>
.
我可能不明白您试图使用可为空扩展解决的确切问题,但您可能希望将可为空包装到您自己的引用类型中,为包装器编写一个 DataTemplate 并使用DataTemplate.Triggers
,选择内容外观。好吧,这看起来像是重新发明的数据模板选择器:)...
NB: I'm not a MS guy, and my findings are based on Reflector and my own experience (which is not as big as I would like it to be
). In any case, hope I could help :).
Cheers