OneNote: An In-Depth Look at the OneNoteImporter Managed Assembly (Part 2 of 5)

In part one, we started to take an in-depth at the OneNoteImporter manage class, which provides an object model interface for the programmability functionality added in OneNote 2003 SP 1.

Read part one here.

Creating Objects

Creating the page and the object you want to import onto it is relatively straight-forward. The Page, PageObject-derived sub-classes, and OutlineContent-derived sub-classes all have one or more public constructors with which you create new instances. We should, however, briefly touch on a few issues to keep in mind.

Identifying Objects

Both the Page and PageObject-derived sub-classes have an internal Id property, which gets or sets an ObjectId object. The ObjectId represents the globally unique identifier (GUID) OneNote requires to identify each page and object imported. The data in an ObjectId consists of a private field representing the containing object’s identifier. The ObjectId object is generated when the page or object is constructed.

The ObjectId object cannot be accessed from outside the assembly. The OneNoteImporter assembly generates and maintains the GUIDs for the user. If you are programming for a scenario that requires you to have access to the GUIDs, there are two approaches to consider:

· Override the class, and make the GUID properties publicly accessible.

· Serialize and persist the Page object between sessions, and then deserialize it as necessary.

Note that the ObjectId class stores the object GUID internally as a System.Guid data type, which does not store the GUID in registry format, that is, surrounded by curly braces ({}). OneNote only accepts GUIDs in registry format. Therefore, the ObjectId.ToString method has been overridden so that it wraps the guid value in curly braces before returning the string.

Similarly, if you use the ObjectId(string) overloaded constructor, the constructor code strips off curly braces, if present. As they might be, if you were passing a serialized ObjectId as an argument.

Committing Objects for Importing

The CommitPending property determines whether or not an import node is included in the XML passed to the SimpleImporter.Import method. Objects with this property set to True represent one of the following:

· an object that hasn’t been imported into OneNote

· an object which as been changed since the last time it was imported; this includes objects marked for deletion from OneNote

· an object that contains a child object that is either of the two cases above

Only objects whose CommitPending property is set to True are serialized and included in the import XML string. By default, whenever an object is constructed from an ImportNode-derived class, this property is set to True. Let’s examine how this property is used, and when they value is changed.

Calling the Page.Commit method imports the page and its contents into OneNote. Once you import a page, the CommitPending property is set to False for that Page object and all the objects contained on it. If you immediately called the Commit method again, neither the page nor any of the objects on it would be included in the XML for the next import.

However, when you make a change to an object, such as changing a property value, the CommitPending property gets set back to True. Not only that, but the CommitPending property of any parent object gets set to True as well. This happens because of the way the import XML is structured. If you want to re-import a specific object, you must also include information about all the objects that contain it, such as the page it appears on. Setting the CommitPending property to True for all the parent objects ensure all the necessary information is included in the import XML string.

Here’s how it actually happens in the code:

You cannot access the CommitPending property from outside the OneNoteImporter class assembly, but if you change any public object properties, the CommitPending property is set to True, so that those object changes are imported into OneNote the next time you call the Page.Commit method. This includes setting the DeletePending property of an object to True.

In addition, the CommitPending property code also sets the CommitPending property of the parent object, if there is one, to True. Which in turns calls the CommitPending property code again, in case that parent object has a parent, and so on up the import node structure to the Page object.

Conversely, when the Commit method sets a Page object’s CommitPending property to False, the property code sets the CommitPending property of any children to False as well, which in turn calls the method again, in case any of those objects have children, and so on.

Adding Objects to Pages and Outlines

You can add content directly to a page, and to an outline on a page. The public Page.AddObject and OutlineObject.AddContent methods both call the internal ImportNode.AddChild method, which adds the child object to a private ArrayList object. A convenience constructor enables you to name the object when you add it, if you want.

OutlineContent objects are displayed in the order in which they are added to the OutlineObject object.

To import text into a OneNote page, you add an HtmlContent object to an OutlineObject, and then add the OutlineObject to the desired Page object.

Deleting Objects From OneNote

In the OneNoteImporter assembly, there are two levels of deleting objects:

· Marking an object for deletion the next time the page is imported into OneNote

· Removing an object from the OneNoteImporter object structure; for example, as removing an ImageContent object from an OutlineObject object

To delete an object from a OneNote page, use the Page.DeleteObject method. This method does not directly remove the object from the Page object’s private children array. Rather, it sets the DeletePending property of the specified object to True. Therefore, when you execute the Page.Commit method, the object gets deleted from the page in OneNote. Only then is the ImportNode.RemoveChild method called. It is this internal method that removes the object from the Page object’s array, using the ArrayList.Remove method. The RemoveChild method also sets the Page object’s CommitPending property to True; however, the Commit method then sets it to False.

Note You can even call the DeleteObject method for objects that have not been imported into OneNote. While this means the object is serialized and included in the XML string passed to the SimpleImporter.Import method, no error results. OneNote ignores XML elements directing it to delete objects not present on the specific page. This is by design, since the OneNote user may have manually deleted the object themselves.

Conversely, to remove an object from an outline, use the OutlineObject.RemoveContent method, which directly calls the ImportNode.RemoveChild method. So the object is removed from the OutlineObject object’s children array at the time the RemoveContent method executes. The RemoveChild content also sets the CommitPending property of the OutlineObject object to True, so that the entire updated outline (minus the removed object) is imported into OneNote again the next time the Page.Commit method executes.

Iterating through an import node’s children

Both the Page and OutlineObject objects implement the IEnumerable interface. Their respective public GetEnumerator methods provide the ability to iterate through their private children array.

In part three, we'll get to the whole point of the OneNoteImporter class: importing objects into OneNote.

Read part three here.