在XAML解析的上下文中,我想知道解析器在类型定义NameScope时如何知道。
是否完全依赖于INameScope界面,检查instance is INameScope
?
它是否依赖于布尔属性XamlType.IsNameScope?
两者兼而有之吗?
答案 0 :(得分:6)
Microsoft文档有一些很好的信息:
默认情况下,当由.NET Framework XAML Services API使用时,主XAML名称范围在单个XAML生产的XAML根元素中定义,并包含该XAML生产中包含的元素
这里要说的是,任何Xaml文档中的根元素都有为其创建的名称范围。无论该元素是否实现INameScope
(事实上,没有核心UI元素),无论都会发生。
可以在单个XAML生成中发生的其他离散XAML名称范围可以由框架定义以解决特定方案。例如,WPF中的,新的XAML名称范围由任何模板定义和创建,该模板也在该XAML生产中定义。有关XAML名称范围(为WPF编写但与许多XAML名称范围概念相关)的更多信息,请参阅WPF XAML Namescopes。
除了为根元素创建的名称范围之外,还为Xaml生产中定义的任何模板隐式创建名称范围。这应该不足为奇,因为FrameworkTemplate
实现了INameScope
,因此DataTemplate
和ControlTemplate
也是如此。还为Style
元素创建了名称范围。
您可能会注意到ResourceDictionary
也实现了INameScope
,但它有点边缘情况:资源字典中的对象名称实际上 <运行时名称范围。如果您查看实现,您会看到其INameScope
方法抛出NotSupportedException
,不执行任何操作或返回null
。这种设计使名称很好地包含在内。它们被禁止在任何父作用域中注册,同时使它们可用于有限的目的,例如在ElementName
上使用Binding
引用。重申一下,资源词典作为名称范围是一个边缘情况,实际上,你应该永远不必考虑。
除了上面概述的隐式创建的作用域之外,还为任何对象创建节点的Xaml解析器框架创建了一个新的名称作用域,其中创建的对象实现了INameScope
。与所有名称范围一样,注册名称在该范围内必须是唯一的 ;但是,它们可能会与堆栈中其他名称范围内的名称发生冲突。
当从Xaml实现对象时,XamlObjectWriter
通过向上移动堆栈查找具有名称范围的帧来解析名称,一旦找到包含所需名称的范围就停止。例如,在从x:Reference
指令评估延迟引用时会发生这种情况。
是否完全依赖
INameScope
界面,检查instance is INameScope
?
它是否依赖于boolean
属性XamlType.IsNameScope
?
通常是后者,但通过确定类型是否可分配给映射到INameScope
的Xaml System.Windows.Markup.INameScope
类型来设置该标志。它不检查运行时实例,而是检查相应对象创建节点的XamlType
。从概念上讲,检查类似于typeof(INameScope).IsAssignableFrom(instanceType)
。
虽然你没有问过,但为了完整起见,我想谈谈最后一点:
何时在名称范围内注册对象?
这是在两种情况下发生的:
x:Name
伪属性; FrameworkElement.Name
之类的属性,该属性被定义为运行时名称属性。 FrameworkElement
之类的类型拥有自己的Name
属性,而不是强制开发人员分别指定Name
和x:Name
,而是提供了一种将CLR属性映射到x:Name
。如果您查看FrameworkElement
的来源,您会看到[RuntimeNameProperty("Name")]
属性。这告诉Xaml基础结构任何Name
上的FrameworkElement
属性对应x:Name
,设置一个属性也会导致另一个属性设置。请注意,运行时名称属性可以具有任何有效名称;它不需要被称为Name
。