Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does a XAML parser identify NameScopes?

In the context of XAML parsing, I would like to know how does the parser know when a type defines a NameScope.

Does it rely entirely on the INameScope interface, checking instance is INameScope?

Does it rely on the boolean property XamlType.IsNameScope?

Is it a mix of both?

like image 630
SuperJMN Avatar asked Feb 21 '26 07:02

SuperJMN


1 Answers

The Microsoft documentation has some good information on this:

By default when used by .NET Framework XAML Services API, the primary XAML namescope is defined at the XAML root element of a single XAML production, and encompasses the elements that are contained in that XAML production.

The takeaway here is that the root element in any Xaml document has a name scope created for it. This happens regardless of whether the element implements INameScope (and, in fact, no core UI elements do).

Additional discrete XAML namescopes that might occur within a single XAML production can be defined by frameworks to address specific scenarios. For example, in WPF, new XAML namescopes are defined and created by any template that is also defined on that XAML production. For more information about XAML namescopes (written for WPF but relevant for many XAML namescope concepts), see WPF XAML Namescopes.

In addition to the name scope created for the root element, name scopes are implicitly created for any template defined within a Xaml production. This should not be surprising, as FrameworkTemplate implements INameScope, and thus so do DataTemplate and ControlTemplate. Name scopes are also created for Style elements.

You may notice that ResourceDictionary also implements INameScope, but it is a bit of an edge case: names of objects in a resource dictionary are not actually registered in any runtime name scope. If you look at the implementation, you will see that its INameScope methods either throw a NotSupportedException, do nothing, or return null. This design keeps the names nicely contained. They are prevented from being registered in any parent scope, while making them available for limited purposes like using an ElementName reference on a Binding. To reiterate, resource dictionaries as name scopes are an edge case that, practically speaking, you should never have to think about.

Beyond the implicitly created scopes outlined above, a new name scope is created for the Xaml parser frame of any object creation node where the created object implements INameScope. As with all name scopes, registered names must be unique within that scope; they may, however, collide with names in other names scopes further up the stack.

When materializing an object from Xaml, the XamlObjectWriter resolve names by walking up the stack looking for frames with name scopes, stopping once it finds a scope containing the desired name. This would happen, for example, when evaluating a deferred reference from an x:Reference directive.

Does it rely entirely on the INameScope interface, checking instance is INameScope?
Does it rely on the boolean property XamlType.IsNameScope?

Generally the latter, but that flag is set by determining whether a type is assignable to the Xaml INameScope type, which maps to System.Windows.Markup.INameScope. It does not check the runtime instance, but rather the XamlType of the corresponding object creation node. Conceptually, the check is similar to typeof(INameScope).IsAssignableFrom(instanceType).

Although you didn't ask it, I'd like to address one final point for the sake of completeness:

When is an object registered in a name scope?

This happens under two conditions:

  1. You explicitly set the x:Name pseudo-property on a Xaml element;
  2. You set a property like FrameworkElement.Name, which is defined as a runtime name property.

Types like FrameworkElement have their own Name property, and rather than forcing developers to specify Name and x:Name separately, they provided a way to map the CLR property to x:Name. If you look at the sources for FrameworkElement, you will see a [RuntimeNameProperty("Name")] attribute. This tells the Xaml infrastructure that the Name property on a any FrameworkElement corresponds to x:Name, and setting one should result in the other being set as well. Note that the runtime name property can have any valid name; it needn't be called Name.

like image 171
Mike Strobel Avatar answered Feb 23 '26 00:02

Mike Strobel