XAML解析器如何识别NameScopes?

时间:2015-08-29 17:02:53

标签: .net wpf xaml parsing

在XAML解析的上下文中,我想知道解析器在类型定义NameScope时如何知道。

是否完全依赖于INameScope界面,检查instance is INameScope

它是否依赖于布尔属性XamlType.IsNameScope?

两者兼而有之吗?

1 个答案:

答案 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,因此DataTemplateControlTemplate也是如此。还为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)

虽然你没有问过,但为了完整起见,我想谈谈最后一点:

  

何时在名称范围内注册对象?

这是在两种情况下发生的:

  1. 您在Xaml元素上显式设置x:Name伪属性;
  2. 您设置了FrameworkElement.Name之类的属性,该属性被定义为运行时名称属性
  3. FrameworkElement之类的类型拥有自己的Name属性,而不是强制开发人员分别指定Namex:Name,而是提供了一种将CLR属性映射到x:Name。如果您查看FrameworkElement的来源,您会看到[RuntimeNameProperty("Name")]属性。这告诉Xaml基础结构任何Name上的FrameworkElement属性对应x:Name,设置一个属性也会导致另一个属性设置。请注意,运行时名称属性可以具有任何有效名称;它不需要被称为Name