XAML Namescopes and JavaScript API


Using the JavaScript API, there are some technical differences in how XAML namescopes are created and used. Also, an XML namespace is not required in the root of the XAML; the Silverlight client XML namespace is inferred.

The primary technical difference at a programming model level is that a name in the XAML namescope can no longer be treated directly as an object in the JavaScript scripting calls. The name must be considered to be conceptually just a string at this stage. To generate a true JavaScript object reference to an object defined in the XAML, you must pass the Name string from the original XAML to the FindName utility method called from JavaScript.

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 XAML namescopes within a Silverlight-based application using the JavaScript API.

In the JavaScript API, 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.

CreateFromXaml has an important XAML namescope behavior difference as compared to the managed XamlReader.Load. Using the default (one-parameter) signature of CreateFromXaml, a preliminary XAML namescope is created, based on the root of the provided XAML. This preliminary XAML 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. If names in the provided XAML collide with names that are already in the primary Silverlight namescope, no errors occur immediately. When the CreateFromXaml method is called, the created object tree that is returned is disconnected. As with the managed XamlReader.Load usage, 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. This is because rather than maintaining the XAML namescopes discretely, by default the behavior in the JavaScript API is to attempt to merge the XAML namescopes whenever two formerly separate object trees are joined. 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).

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 also creates a preliminary XAML namescope that evaluates any defined names in the provided XAML for uniqueness. The difference in the behavior for the createNameScope=true case is that the disconnected object tree is now flagged to not attempt to merge its XAML namescope with the main application XAML namescope when the object trees are joined. Generally, this behavior resembles the discrete XAML namescope considerations mentioned in the previous sections for the managed API. To get to objects that are defined in a different XAML namescope, you can use several techniques in the JavaScript API (these techniques parallel managed equivalent techniques):

  • Walk the entire tree in discrete steps with GetParent and/or collection properties.

  • If you are calling from a discrete XAML namescope and want the main application namescope, you can 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 XAML namescope. The .content in 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 XAML namescope and want an object within a discrete XAML 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 object tree. This object is now a valid object for calling FindName within the created discrete XAML namescope.

The FindName method defined on the Silverlight plug-in object does not entirely work around the disconnected XAML namescope problems of CreateFromXaml described in this topic; its XAML namescope is always the root XAML namescope.

Inline XAML is a technique where XAML can be defined in the HTML that hosts the Silverlight plug-in rather than in a separate XAML file. Because of its position in the browser DOM, inline XAML constitutes a deliberate choice to use the JavaScript API, even if a managed-code capable version is specified during Silverlight initialization. (Without a discrete XAML file that is known to a managed project file, which specifies x:Class at its root, there is no way for an inline XAML solution to know how to connect the code-behind and XAML, and no specific instruction to compile and connect the managed code.) XAML namescopes in the JavaScript API act identically, whether XAML content is defined as inline XAML or as a file that is entirely XAML. The XAML namescope is defined on the basis of the root of the XAML portion, as if it were the root of a XAML file.

Community Additions