This section covers VSTO 2005's support for Word's schema mapping. Let's create a new VSTO 2005 Word project based on the book-order document we created in this chapter. Launch VSTO 2005, and from the New submenu of the File menu, choose Project. In the New Project dialog box, select a Visual Basic Word document project. Give the project a name and location, and then click the OK button. A dialog box appears, asking for a document to be used for the application. Click the Copy an Existing Document radio button. Then click the ellipsis (...) button to browse to the document you created in this chapter that has the book-order schema mapped in it. Click the Finish button to create the project. We want to consider several features of the generated VSTO project. First is the creation of XMLNode controls. Second is the creation of XMLNodes controls. Finally, we will consider how to use the UpdateXml methods on an XMLNode to load XML into our document without using an XSLT file. Use the class view to browse the members associated with ThisDocument. Notice as you browse that the member variables listed in Table 22.1 have been created automatically, based on the XML mapping in the document to the book-order schema. Table 22.1. ThisDocument Member Variables Added from Schema MappingName | Type |
---|
OrderNode | Microsoft.Office.Tools.Word.XMLNode | OrderCustomerNameNode | Microsoft.Office.Tools.Word.XMLNode | OrderDateNode | Microsoft.Office.Tools.Word.XMLNode | OrderBookNodes | Microsoft.Office.Tools.Word.XMLNodes | BookTitleNodes | Microsoft.Office.Tools.Word.XMLNodes | BookISBNNodes | Microsoft.Office.Tools.Word.XMLNodes | BookPublisherNodes | Microsoft.Office.Tools.Word.XMLNodes | BookPriceNodes | Microsoft.Office.Tools.Word.XMLNodes | OrderSubtotalNode | Microsoft.Office.Tools.Word.XMLNode | OrderTaxNode | Microsoft.Office.Tools.Word.XMLNode | OrderTotal Node | Microsoft.Office.Tools.Word.XMLNode |
The XMLNode Control For each nonrepeating element mapped to the Word document, VSTO creates an XMLNode control. By mapping the nonrepeating element CustomerName from the Order element, for example, VSTO created an XMLNode control called OrderCustomerNameNode. An XMLNode control has all the properties and methods of a Word XMLNode object. In addition, it has several events that are not found on the Word XMLNode object: XMLNode.AfterInsert is raised when a new XML element is added to the document. XMLNode.BeforeDelete is raised when an XML element is removed from the document. XMLNode.ContextEnter is raised when the XML node has focus. XMLNode.ContextLeave is raised when the XML node loses focus. XMLNode.Select is raised when text within the XML node is selected. XMLNode.Deselect is raised when text within the XML node is deselected. XMLNode.ValidationError is raised when a validation error occurs within the XML node. Listing 22.5 shows a VSTO customization that handles all the events associated with an XMLNode. In this case, the code handles events associated with the XMLNode called OrderCustomerNameNode, which corresponds to the CustomerName element from the book-order schema mapped into the Word document. Listing 22.5. A VSTO Word Customization That Handles All Events Associated with an XMLNode Control Imports Word = Microsoft.Office.Interop.Word Imports Office = Microsoft.Office.Core Public Class ThisDocument Private list As System.Windows.Forms.ListBox Private Sub ThisDocument_Startup(ByVal sender As Object, _ ByVal e As EventArgs) Handles Me.Startup list = New System.Windows.Forms.ListBox ActionsPane.Controls.Add(list) ActionsPane.Show() End Sub Private Sub Display(ByVal text As String, _ ByVal text2 As String) list.Items.Add(String.Format("{0} {1}", text, text2)) End Sub Private Sub OrderDateNode_AfterInsert( _ ByVal sender As Object, _ ByVal e As _ Microsoft.Office.Tools.Word.NodeInsertAndDeleteEventArgs) _ Handles OrderDateNode.AfterInsert Dim node As Microsoft.Office.Interop.Word.XMLNode = sender Display("AfterInsert", node.BaseName) End Sub Private Sub OrderDateNode_BeforeDelete( _ ByVal sender As Object, _ ByVal e As _ Microsoft.Office.Tools.Word.NodeInsertAndDeleteEventArgs) _ Handles OrderDateNode.BeforeDelete Dim node As Microsoft.Office.Interop.Word.XMLNode = sender Display("BeforeDelete", node.BaseName) End Sub Private Sub OrderDateNode_BindingContextChanged( _ ByVal sender As Object, ByVal e As EventArgs) _ Handles OrderDateNode.BindingContextChanged Display("BindingContextChanged", "") End Sub Private Sub OrderDateNode_ContextEnter( _ ByVal sender As Object, _ ByVal e As _ Microsoft.Office.Tools.Word.ContextChangeEventArgs) _ Handles OrderDateNode.ContextEnter Display("ContextEnter", e.NewXMLNode.BaseName) End Sub Private Sub OrderDateNode_ContextLeave( _ ByVal sender As Object, _ ByVal e As _ Microsoft.Office.Tools.Word.ContextChangeEventArgs) _ Handles OrderDateNode.ContextLeave Display("ContextLeave", e.NewXMLNode.BaseName) End Sub Private Sub OrderDateNode_Select(ByVal sender As Object, _ ByVal e As _ Microsoft.Office.Tools.Word.ContextChangeEventArgs) _ Handles OrderDateNode.Select Display("Select", e.Selection.Text) End Sub Private Sub OrderDateNode_Deselect(ByVal sender As Object, _ ByVal e As _ Microsoft.Office.Tools.Word.ContextChangeEventArgs) _ Handles OrderDateNode.Deselect Display("Deselect", e.Selection.Text) End Sub Private Sub OrderDateNode_ValidationError( _ ByVal sender As Object, _ ByVal e As EventArgs) Handles OrderDateNode.ValidationError Display("ValidationError", "") End Sub End Class | The XMLNodes Control For each repeating element mapped to the Word document, VSTO creates an XMLNodes control. For the repeating element Book from the Order element, VSTO created an XMLNodes control called OrderBookNodes. An XMLNodes control has all the properties and methods of a Word XMLNodes object. In addition, it has several events that are not found on the Word XMLNodes object: XMLNodes.AfterInsert is raised when a new XML element is added to the document. XMLNodes.BeforeDelete is raised when an XML element is removed from the document. XMLNodes.ContextEnter is raised when an element contained by the XMLNodes control gets focus. XMLNodes.ContextLeave is raised when an element contained by the XMLNodes control loses focus. XMLNodes.Select is raised when text within the elements contained by the XMLNodes control is selected. XMLNodes.Deselect is raised when text within the elements contained by the XMLNodes control is deselected. XMLNodes.ValidationError is raised when a validation error occurs within the elements contained by the XMLNodes control. Listing 22.6 shows a VSTO customization that handles all the events associated with an XMLNodes control. The code handles events associated with the XMLNodes control called OrderBooksNodes, which corresponds to the repeating Book element from the book-order schema that was mapped into the Word document. Listing 22.6. A VSTO Word Customization That Handles All Events Associated with an XMLNodes Control Imports Word = Microsoft.Office.Interop.Word Imports Office = Microsoft.Office.Core Public Class ThisDocument Private list As Windows.Forms.ListBox Private Sub ThisDocument_Startup(ByVal sender As Object, _ ByVal e As EventArgs) Handles Me.Startup list = New Windows.Forms.ListBox ActionsPane.Controls.Add(list) ActionsPane.Show() End Sub Private Sub Display(ByVal text As String, _ ByVal text2 As String) list.Items.Add(String.Format("{0} {1}", text, text2)) End Sub Private Sub OrderBookNodes_AfterInsert( _ ByVal sender As Object, _ ByVal e As _ Microsoft.Office.Tools.Word.NodeInsertAndDeleteEventArgs) _ Handles OrderBookNodes.AfterInsert Dim node As Microsoft.Office.Interop.Word.XMLNode = sender Display("AfterInsert", node.BaseName) End Sub Private Sub OrderBookNodes_BeforeDelete( _ ByVal sender As Object, _ ByVal e As _ Microsoft.Office.Tools.Word.NodeInsertAndDeleteEventArgs) _ Handles OrderBookNodes.BeforeDelete Dim node As Microsoft.Office.Interop.Word.XMLNode = sender Display("BeforeDelete", node.BaseName) End Sub Private Sub OrderBookNodes_ContextEnter( _ ByVal sender As Object, _ ByVal e As _ Microsoft.Office.Tools.Word.ContextChangeEventArgs) _ Handles OrderBookNodes.ContextEnter Display("ContextEnter", e.NewXMLNode.BaseName) End Sub Private Sub OrderBookNodes_ContextLeave( _ ByVal sender As Object, _ ByVal e As _ Microsoft.Office.Tools.Word.ContextChangeEventArgs) _ Handles OrderBookNodes.ContextLeave Display("ContextLeave", e.NewXMLNode.BaseName) End Sub Private Sub OrderBookNodes_Select(ByVal sender As Object, _ ByVal e As _ Microsoft.Office.Tools.Word.ContextChangeEventArgs) _ Handles OrderBookNodes.Select Display("Select", e.Selection.Text) End Sub Private Sub OrderBookNodes_Deselect(ByVal sender As Object, _ ByVal e As _ Microsoft.Office.Tools.Word.ContextChangeEventArgs) _ Handles OrderBookNodes.Deselect Display("Deselect", e.Selection.Text) End Sub Private Sub OrderBookNodes_ValidationError( _ ByVal sender As Object, _ ByVal e As EventArgs) Handles OrderBookNodes.ValidationError Display("ValidationError", "") End Sub End Class | Loading XML Programmatically with LoadXml Another addition that VSTO makes to XMLNode is the LoadXml method. The LoadXml method can be used to set the XML on the entire node tree of the XMLNode on which it is called. The LoadXml method has three overloads that take a String of XML, an XmlElement, or an XmlDocument. LoadXml has one major limitation: It will not decrease or increase the number of XML elements in the document. So, given the code in Listing 22.7 that has three book elements and given a document that has only one book in the table mapped to book elements, LoadXml will transfer only the first book to the document. Transferring the second and third books would require the addition of elements, which LoadXml does not do. As a second example, if you have a document that has three books in the table, and you call LoadXml passing XML with only one book, LoadXml will update the first row of the table but will leave the two extra books there. The second and third books are left there because LoadXml does not remove elements. Listing 22.7. The LoadXml Method on XMLNode Object Private Sub ThisDocument_Startup(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Startup Me.OrderNode.LoadXml( _ "<?xml version=""1.0"" " & _ "encoding=""UTF-8"" standalone=""no""?>" & _ "<Order " & _ "xmlns=""http://dotnet4office.com/bookorder.xsd"">" & _ "<CustomerName>Lah Lah</CustomerName>" & _ "<Date>2005-03-19</Date>" & _ "<Book>" & _ "<Title>Windows Forms Programming in C#</Title>" & _ "<ISBN>0-321-11620-8</ISBN>" & _ "<Publisher>Addison-Wesley</Publisher>" & _ "<Price>49.99</Price>" & _ "</Book>" & _ "<Book>" & _ "<Title>Effective C#</Title>" & _ "<ISBN>0-321-24566-0</ISBN>" & _ "<Publisher>Addison-Wesley</Publisher>" & _ "<Price>39.99</Price>" & _ "</Book>" & _ "<Book>" & _ "<Title>The C# Programming Language</Title>" & _ "<ISBN>0-321-15491-6</ISBN>" & _ "<Publisher>Addison-Wesley</Publisher>" & _ "<Price>29.99</Price>" & _ "</Book>" & _ "<Subtotal>119.97</Subtotal>" & _ "<Tax>10.7973</Tax>" & _ "<Total>130.7673</Total>" & _ "</Order>") End Sub | You frequently will want to get the XML from an XMLNode or XMLNodes. The way you do this is to use the XML property on the Range object returned by the Range property of an XMLNode or XMLNodes. The XML property takes an optional Boolean parameter, to which you pass TRue to get the XML data. If you pass False, you will get the WordML for the XMLNode or XMLNodes instead. Listing 22.8 shows a simple VSTO application that displays the XML data in the document on startup using the root XMLNode called OrderNode. Listing 22.8. Using the XML Property Private Sub ThisDocument_Startup(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Startup MsgBox(Me.OrderNode.XML(True)) End Sub | |