In Microsoft Silverlight, a namescope stores relationships between the XAML-defined names of objects and their instance equivalents. This is similar to the wider meaning of the term "namescope" in other programming languages and technologies. Namescopes are created during the process of loading the XAML source for a Silverlight-based application.
This topic contains the following sections:
- How Namescopes Are Defined
- Using Namescopes at Run Time
- Adding Objects to Silverlight at Run Time
- Creating Namescopes with CreateFromXAML
How Namescopes Are Defined
Namescopes are created by the XAML parser, and associated with the root element for a XAML element tree when the XAML is loaded. Typically, the XAML of the element tree is defined within a single XAML file, which is completely in XAML format. But XAML can also be defined as inline XAML within the HTML, or can be used as the string input for the CreateFromXaml method that is used to initialize new Silverlight objects at runtime.
Each name specified within the XAML is added to the root namescope. A name is established by setting the value for one of two nearly equivalent attributes, Name or x:Name. (For details on the distinction between Name and x:Name, see Remarks in Name.) If you try to define the same name twice in any namescope, an exception will be raised.
In general, attributes in XAML can be specified only on object elements. Property elements (used to provide values for certain Silverlight properties in XAML) cannot have a Name or any other attribute. For details on XAML syntax, see XAML Syntax Overview.
Using Namescopes at Run Time
Names and namescopes enable scripting code to reference the objects that were initially defined in XAML. The internal result of parsing XAML is to create a set of objects that retain some or all of the relationships these objects had in XML, with those relationships maintained as specific object properties of the created objects, or exposed to utility methods in the Silverlight object model. The most useful of these utility methods is FindName. To get an object reference to an object that was defined in XAML, simply use the return value of the FindName method, specifying the name of the object you want to retrieve as an input parameter. FindName works from almost any scope and will search the entire run-time set of objects; you are not limited to searching in particular parent-child axes. However, there are ways to define multiple namescopes within a Silverlight-based application. The effect of this ability on FindName calls is discussed in the following sections.
Namescopes act identically, whether XAML content is defined as inline XAML or as a file that is entirely XAML. The namescope is defined on the basis of the root of the XAML portion, as if it were the root of a XAML file.
Adding Objects to Silverlight at Run Time with CreateFromXAML
In Silverlight 1.0, there is no true constructor syntax available in scripting for Silverlight objects. Instead, you define objects in XAML fragments, which are supplied as the input parameter for the CreateFromXaml method. The object elements that are defined as part of this XAML fragment can also have values defined for Name or x:Name. As part of the CreateFromXaml call, a preliminary namescope is created, based on the root of the provided XAML. This preliminary namescope evaluates any defined names in the provided XAML for uniqueness. If names in the provided XAML are not internally unique at this point, CreateFromXaml throws an error. However, if names in the provided XAML collide with names that are already in the primary Silverlight namescope, no errors occur immediately. This is because when the CreateFromXaml method is called, the created object tree that is returned is disconnected. You must explicitly connect your created object tree, either by adding it to a content property collection such as Canvas.Children or by setting some other property that takes an object value (such as specifying a new ImageBrush for a Fill property value). You will see name collisions causing errors only after you attempt to connect the disconnected object tree to the application's main object tree. The method or property used for the attempted connection will be the source of the error, and the attempted connection will fail (your disconnected tree will remain disconnected).
Creating Namescopes with CreateFromXAML
CreateFromXaml has an optional parameter, createNameScope, which normally defaults to false. Explicitly setting this value to true in the CreateFromXaml call that you use to create a disconnected object tree still creates a preliminary namescope that evaluates any defined names in the provided XAML for uniqueness. If names in the provided XAML are not internally unique at this point, CreateFromXaml throws an error. The difference in the behavior is that the disconnected object tree is now flagged to not attempt to merge its namescope with the main application namescope when it is connected to the main application object tree. After you connect the trees, in effect, your application will have a unified object tree but discrete namescopes. A name defined at the CreateFromXaml root or on any object in the previously disconnected tree is not associated with the main application namescope; it has its own discrete namescope.
The complication with having discrete namescopes is that calls to the FindName method no longer work on a unified scope/namescope. Instead, the particular object that FindName is called on will imply the scope, with the scope being the namescope that the calling object is within. Therefore, if you attempt to call FindName to get a named object in the main application namescope, it will not find the objects from a discrete namescope created by CreateFromXaml. Conversely, calling FindName from the discrete namescope will not find named objects in the main application namescope. The FindName method defined on the Silverlight plug-in object does not entirely work around this issue; its namescope is always the main application namescope.
This discrete namescope issue only affects namescopes and the FindName call. You can still walk discrete steps upward in some cases by calling the GetParent method, or walk discrete steps downward by calling into the relevant collection properties or properties (such as the collection returned by Canvas.Children).
To get to objects that are defined in a different namescope, you can use several techniques:
Walk the entire tree in discrete steps with GetParent and/or collection properties.
If you are calling from a discrete namescope and want the main application namescope, it is always easy to get a reference to the Silverlight plug-in and then call FindName on it. The concatenated script call for doing this in a single line is as follows:
returnedObject = object.GetHost().content.FindName("nameToFind");
where object is the calling object in a discrete namescope. The
.contentin this syntax is the step through to the specific Silverlight plug-in sub-object that defines the FindName method.
If you are calling from the main application namescope and want an object within a discrete namescope, the best thing to do is to plan ahead in your code and retain a reference to the object that was returned by CreateFromXaml and then added to the tree. This object is now a valid object for calling FindName within the created discrete namescope. You could keep this object as a global variable or otherwise pass it by using method parameters.