XML Notepad Design#
By Chris Lovett, Microsoft
In the GitHub repo, you'll find the core XmlNotepad DLL project, an Application project that builds XmlNotepad.exe,
and some setup projects like XmlNotepadSetup which builds the .msi installer, and the UnitTests project for testing
XML Notepad.
The following DGML diagram shows the relationships between the main UI classes. The main form contains all the UI elements from the TaskList to the main XmlTreeView with Resizers in between; it's the launching point for the dialogs such as FormSearch, FormSchemas, FormOption, and FormAbout.

The main tab control contains the XmlTreeView and the XsltViewer for showing XSL output. The XmlTreeView contains a TreeView on the left and a NodeTextView on the right and coordinates scrolling between these two views. Both the TreeView and NodeTextView provide the same IntelliSense editing functionality using a TextEditorOverlay component. The XmlTreeView implements IFindTarget, which is used by the Find dialog (FormSearch) to implement find/replace functionality.

The Find dialog supports full text, regex, or XPath expressions and can filter by names or values.
Model#
The core data model behind the UI is System.Xml.XmlDocument and its XmlNode objects. These nodes are wrapped by
TreeNode UI objects. To facilitate support for the XML Include spec, there is a custom reader that processes XML
Includes, and there is also a custom DomLoader that keeps track of line information for error messages.

Validation, IntelliSense, and Custom Editors#
The biggest new feature is IntelliSense, which is driven by XML Schema information provided via the SchemaCache. For example, if your element or attribute is defined by an XSD simpleType and this simpleType contains a list of enumeration facets, then you will get a drop-down like this:

The way this works is that the Checker runs after each edit operation to validate the document and report errors in the
TaskList. This process also puts System.Xml.Schema.XmlSchemaType information on each element and attribute in the
XmlDocument; then, when editing the value of that node, the TextEditorOverlay uses the XmlIntelliSenseProvider to get
back a list of possible values. In the above example, it returns the values from the simpleType enumeration facets. For
element name IntelliSense in the tree view, the XmlIntelliSenseProvider invokes the Checker again, captures
GetExpectedParticles and GetExpectedAttributes on the System.Xml.Schema.XmlSchemaValidator, and uses that to provide
IntelliSense.

The TextEditorOverlay also supports custom editors like the DateTimeEditor or the UriBuilder or ColorBuilder.
There are two types of custom editors: IXmlEditors, which are inline editors that replace the default TextBox, and
IXmlBuilders, which are popup dialogs like the OpenFileDialog or ColorDialog. The type of editor is derived from the
schema type information — "xs:date", "xs:time", "xs:datetime" results in the DateTimeEditor, and "xs:anyURI" results in
the UriBuilder. You can also annotate the schema with a custom "vs:builder" attribute in the
http://schemas.microsoft.com/Visual-Studio-IntelliSense namespace. See the Help content for more information.
Infinite Undo/Redo#
To implement undo/redo, XML Notepad follows a common design pattern of Command objects with Undo and Redo methods.
Commands operate on both a TreeNode and an XmlNode because some commands like InsertNode don't have an XmlNode
yet until they are performed, but the command needs to know where in the tree this new node will be inserted and during
Undo where it should be removed. The UndoManager collects these in a list. Then the state of the UndoManager controls
the enabled/disabled state of the Undo/Redo MenuItems. When the user selects the Undo menu item, the Undo method is
called on the active command, and that command is pushed onto the Redo stack.

Some operations in the editor cause many edits in the tree, including the replace-all operation and editing the value of
a namespace attribute. (When you change the value of a namespace attribute, every XmlNode bound to that namespace needs
to be reconstructed with a new namespace URI, which can obviously affect a lot of nodes in the tree!) So, to make these
operations one atomic undo operation, there is a CompoundCommand object that contains a list of smaller edit commands,
and this CompoundCommand is put into the UndoManager.
Other simpler command objects include the following, which all operate on XmlTreeNode and XmlNode objects:

The PasteCommand is special because it takes random XML text off the clipboard and parses it in the context of the currently selected element in the tree, inheriting the namespaces in scope. The helper class TreeData uses the special XmlTextReader constructor that takes an XmlParserContext as input.
Accessibility#
In order to make testing possible using System.Windows.Automation, there are some custom AccessibleObject
implementations inside the TreeView and NodeTextView. See AccessibleNode and AccessibleNodeTextViewNode. These
accessibility classes should also make Windows accessibility features work better with those custom views.
Missing Documentation?#
If you want more detailed documentation on some aspect of XML Notepad, please create a new GitHub issue.