使用自定义类型扩展名指定DataTemplate.DataType

编程入门 行业动态 更新时间:2024-10-21 23:22:15
本文介绍了使用自定义类型扩展名指定DataTemplate.DataType的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有这个标记扩展名

public class NullableExtension : TypeExtension { public NullableExtension() { } public NullableExtension( string type ) : base(type) { } public NullableExtension( Type type ) : base(type) { } public override object ProvideValue( IServiceProvider serviceProvider ) { Type basis = (Type)base.ProvideValue( serviceProvider ); return typeof(Nullable<>).MakeGenericType( basis ); } }

旨在提供其他版本的可空版本类型。在普通 XAML中使用时,它可以按预期工作。例如,如

which is designed to provide a nullable version of some other type. It works as expected when used in "normal" XAML. For example, as in

<SomeControl DataContext="{My:Nullable System:Int32}"/>

(假设My是为包含扩展名的C#名称空间定义的XML名称空间,同样对于System )。如我所料,该控件的数据上下文已设置为 Nullable< int> 的 System.Type 。

(assuming that My is the XML namespace defined for the C# namespace holding the extension, and similarly for System). The data context for the control gets set to a System.Type for Nullable<int> as I expect.

但是,当我使用此扩展程序尝试设置 DataTemplate <的 DataType 属性时, / code>像

However, when I use this extension to try and set the DataType property of a DataTemplate like

<DataTemplate DataType="{My:Nullable System:Int32}"> <TextBlock ... /> </DataTemplate>

编译器告诉我,

字典的键不能为类型的'System.Windows.Controls.Primitives.TextBlock'。仅支持String, TypeExtension和StaticExtension。

A key for a dictionary cannot be of type 'System.Windows.Controls.Primitives.TextBlock'. Only String, TypeExtension, and StaticExtension are supported."

类型'NullableExtension'的构造函数没有1个参数。

"No constructor for type 'NullableExtension' has 1 parameters.

有人知道为什么吗只允许使用这三种方法(甚至不像我的方法那样允许 TypeExtension 的子类)?那时XAML的处理有什么特别之处?还有没有另一种方法(不基于 DataTemplateSelector 来完成基于数据类型的数据模板选择)吗?

Does anybody know why only those three methods (and not even subclasses of TypeExtension, like mine is) are allowed? What is special about the processing of the XAML at that point? And is there another way to accomplish this (data template selection based on types that may be nullable) without resorting to a DataTemplateSelector?

推荐答案

我真的很想知道您的问题,这就是我所发现的。

I really got into your question, and here is what I found.

Q:为什么只有这三个( String , TypeExtension 和 StaticExtension )被允许?

Q: Why only those three (String, TypeExtension, and StaticExtension) are allowed?

A:是设计使然。如果您可以编写任何自定义标记扩展名来用作字典中的键,这会带来哪些副作用?考虑将Binding作为DataType的值...我敢肯定,您可以添加许多与字典键动态性质相关的问题。

A: By design. If you could write any custom markup extension to be used as a key in a dictionary, what side effects would this introduce? Consider you have Binding as a value of DataType... I'm pretty sure you can add dozen issues related to dictionary keys dynamic nature.

问:那时候处理XAML有何特别之处?

Q: What is special about the processing of the XAML at that point?

A 。此时,您已经创建了BAML。问题来自内部类 BamlRecordWriter ,但该消息未描述实际问题。当您将自定义标记扩展指定为DataType时,它将接受DataTemplate的子,并检查其是否可以从字符串,TypeExtension或StaticExtension分配(请参见 BamlRecordWriter.WriteElementStart()函数)。 。确实。不是您的扩展名(可分配给TypeExtension),而是第一个子级(不可分配)。现在,您有了这个奇怪的 不能属于类型的东西。尽管它看起来像是BamlRecordWriter的错误,但我认为他们是有意离开的。

A. At that point you have BAML creation. The problem comes from internal class BamlRecordWriter, but the message doesn't describe actual problem. When you specify custom markup extension as DataType, it takes a DataTemplate's child, and checks it if it's assignable from string, TypeExtension or StaticExtension (see BamlRecordWriter.WriteElementStart() function). Indeed. Not your extension (which is assignable to TypeExtension), but first child (which is not assignable). Now you have this strange "cannot be of type" thing. Although it looks like a BamlRecordWriter's bug, I think they left it intentionally. Until it doesn't let you use custom markup extension as a DataType value, who cares about error message?

Q:是否有另一种方法可以完成此操作(根据可能为空的类型选择数据模板)而无需使用DataTemplateSelector?

Q: Is there another way to accomplish this (data template selection based on types that may be nullable) without resorting to a DataTemplateSelector?

A:是的,有点。首先,您可以让标准TypeExtension为您完成所有肮脏的工作:

A: Yes, kind of. First of all you can have standard TypeExtension do all the dirty job for you:

<DataTemplate DataType="{x:Type TypeName=System:Nullable`1[[System.Int32]]}"> </DataTemplate>

但是在大​​多数情况下(如果不是一直),您将看不到模板化结果。为什么?现在谈到可空类型的装箱规则。将非null的可为空的值类型装箱,将值类型本身而不是包装该值类型的System.Nullable装箱。因此,默认模板选择器将查找数据类型为 T 而不是 Nullable< T> 的DataTemplate。

But in most of the cases (if not all the time) you will not see the templating results. Why? Now it comes to boxing rules for nullable types. Boxing a non-null nullable value type boxes the value type itself, not the System.Nullable that wraps the value type. Thus default template selector will look for DataTemplate with DataType of T not of Nullable<T>.

我可能不明白您尝试使用可空扩展名解决的确切问题,但是您可能希望将可空变量包装到自己的引用类型中,为包装器编写一个DataTemplate并使用 DataTemplate.Triggers ,以选择内容外观。好吧,这看起来像是重新发明的数据模板选择器:)...

I may not understand exact problem you are trying to solve with nullable extension, but you may want to wrap nullables into your own ref type, write one DataTemplate for the wrapper and use DataTemplate.Triggers, to choose content appearance. Well, this looks like reinvented data template selector :)...

NB:我不是MS专家,我的发现基于Reflector和我自己的经验(它不像我希望的那样大, )。无论如何,希望我能帮忙:)。

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 :).

干杯

更多推荐

使用自定义类型扩展名指定DataTemplate.DataType

本文发布于:2023-11-07 05:30:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1565671.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:扩展名   自定义   类型   DataType   DataTemplate

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!