This wasn’t meant to be a multi-part series, but it seems to turn out that way…
In the first part, I’ve shown how we can leverage some of the new System.Xaml namespace functionality to construct an object tree from a XAML text. This was pretty easy with methods like XamlServices.Load or XamlServices.Parse. However, these methods return the top level (root) object, with all sub objects constructed already, without any way to intervene, or do something with the sub-objects, as they’re being constructed.
To gain access to the sub-objects (and their assigned properties) during the parsing process, we’ll have to abandon the easy XamlServices class and descend deeper using the XamlXmlReader class, and its companion for object creation XamlObjectWriter class.
A basic parsing loop is constructed by calling XamlXmlReader.Read to advance the parser to the next element. Read returns false when the end of input is reached. In each iteration the NodeType property is queried and appropriate action can be taken. The default action should be to call XamlObjectWriter.WriteNode, but additional actions can be taken, such as updating an internal object list, or whatever else is required.
Here’s a typical parsing loop:
public static object Parse(Stream stm) {
// create some custom context as explained in part 1
var ctx = new XamlParserContext();
using(var reader = new XamlXmlReader(stm, ctx)) {
using(var writer = new XamlObjectWriter(ctx)) {
while(reader.Read()) {
switch(reader.NodeType) {
case XamlNodeType.EndObject:
// default action
writer.WriteNode(reader);
// do something with resulting object
DoSomethingWithObject(writer.Result);
break;
default:
// default action (must be done!)
writer.WriteNode(reader);
break;
}
}
// return root object
return writer.Result;
}
}
}
In this code sample, the XamlNodeType.EndObject node is used to perform some custom action on the closing tag of an object. Similar constants exist for members, but they are less frequently used.
In the next installment, I’ll show how we can parse attached properties, similar to the ones that exist in WPF and Silverlight.