XmlDataSource Enhanced
Add Editing, Deleting, and Inserting Capabilities to Your XmlDataSource Controls
October 30, 2009
asp:Feature
LANGUAGES:C# | VB.NET
ASP.NETVERSIONS: 2.0
XmlDataSource Enhanced
Add Editing, Deleting, and Inserting Capabilities toYour XmlDataSource Controls
By Dr. Shahram Khosravi
Tabular data-bound controls, such as GridView andDetailsView, expect tabular data from the underlying data store. Hierarchicaldata-bound controls, on the other hand, such as TreeView and Menu, expecthierarchical data. This causes a big problem in data-driven Web applicationswhere data comes from different sources, such as Microsoft SQL Server, Oracle,Microsoft Access, XML documents, flat files, and Web services, just to name afew.
There is no guarantee that the underlying data store willalways return tabular data to tabular data-bound controls, or hierarchical datato hierarchical data-bound controls. Let s consider an example. Imagine aGridView control in the Web application of an organization that displaystabular data (e.g. products information) coming from the Microsoft SQL Serverdatabase of one of the company s clients. Suppose that the company decides toprovide services to a new client where the data comes from XML documents. Thiscould be because either the client stores its products information in XMLdocuments or the client uses XML Web services to expose its productsinformation as XML. Either way, the new client will not return tabular data tothe GridView control.
The ASP.NET 2.0 data source controls isolate data-boundcontrols from the underlying data store and present them with the appropriateviews of the data store. They present tabular data-bound controls with thetabular views, whether or not the data store is tabular, and hierarchicaldata-bound controls with the hierarchical views, whether or not the data storeis hierarchical.
Data source controls that implement the IDataSourceinterface expose tabular views and those that implement theIHierarchicalDataSource interface expose hierarchical views. The XmlDataSourcecontrol is in a unique position because it implements both the IDataSource andIHierarchicalDataSource interfaces. Therefore, it exposes both tabular andhierarchical views of its underlying XML document, allowing both tabular andhierarchical data-bound controls to be bound to it. This article will develop aWeb application that uses both tabular and hierarchical views of theXmlDataSource control.
The main problem with the XmlDataSource control is that itdoesn t provide built-in support for Delete, Update, or Insert data operations.This is a major issue in XML-based Web applications where XML documents areused as a data store. This article shows how we can use the underlyingXmlDocument object of the XmlDataSource control to add support for otheroperations, such as Delete, Insert, and Update.
Tree Representation and Location Paths
This article presents the implementation of an XML-basedthreaded discussion forum, where an XML document is used as its data store.Figure 1 shows part of the XML document.
Looking for a good book onASP.NET I'm looking for a book with lotof examples. Are you looking for a book for beginners? What kind of book are you lookingfor? Books for beginers with lot of examples I'm looking for a book withlot of examples What sort of examples? Could you be more specific? Examples with practical applications Code examples that I could use in my work New ASP.NET books are comingout You may want to check outamazon.com for new books on ASP.NET Thanks, I will I will check out amazon.com. Imay get lucky there. Any one have code examples fordata source controls I need codeexamples that show how to use data source controls in bigapplications What type of data sourcecontrols? There are all kinds of datasource controls. Which ones are youplanning on using? Figure 1: Themessages.xml file. A element represents a posted messagewhere the and child elements contain the subjectand body of the message, respectively. The AddedDate and UserName attributes ofa given element represent the date the message was posted andthe user name of the author, respectively. The XmlDataSource control must first load the documentinto memory. In general, there are two loading models: streaming and DOM(Document Object Model). The streaming model reads in the XML document as astream of nodes where only the current node is kept in memory. TheXmlDataSource control uses the W3C DOM model to load the entire contents of themessages.xml file into an instance of the XmlDocument class and generate thein-memory tree representation of the document, as shown in Figure 2.
Figure 2: The in-memory treerepresentation of the messages.xml file. Let s compare the XmlDataSource and SqlDataSource loadingmodels. The SqlDataSource control loads the underlying database tables into aninstance of the DataSet class and generates the in-memory tabularrepresentation of the underlying tables. The in-memory tabular representationconsists of interconnected rows where each row is an instance of the DataRowclass. Now compare that with the in-memory tree representation, suchas shown in Figure 2, which consists of interconnected nodes where each node isan instance of the XmlNode class. The XmlNode class is an abstract class thatrepresents any type of node. Each of its subclasses represents a particulartype of node. For instance, the XmlElement subclass represents element nodes,i.e. , , and ; the XmlAttributesubclass represents attribute nodes, i.e. AddedDate and UserName. When we select, delete, insert, or update a row in aDataSet object, we don t directly select, delete, insert, or update thecorresponding row in the underlying database table, because the DataSet objectis not connected to the database. In other words we select, delete, insert, orupdate the row in the in-memory tabular representation of the database table,not the database table itself. This is why the changes to the in-memory tabularrepresentation must be explicitly committed to the underlying database tables. The same argument applies to the XmlDocument object thathas been loaded with the data from the underlying messages.xml file. When weselect, delete, insert, or update a node in the XmlDocument object, we don tdirectly select, delete, insert, or update the corresponding node in theunderlying XML document, because the XmlDocument object isn t connected to theXML document itself. In other words, we select, delete, insert, or update thenode in the in-memory tree representation of the XML document, not the documentitself. This is why the changes to the in-memory tree representation must beexplicitly committed to the underlying XML document. To modify a row or node in the underlying data store we mustfirst modify the row or node in the corresponding tabular or treerepresentation, then commit the changes. Because a tabular or treerepresentation is a collection of rows or nodes, we cannot work with a row ornode in the collection until we first locate and identify that row or node inthe collection. Page developers use the primary key of a row to uniquelylocate and identify the row in the underlying tabular representation. Theprimary key of a row plays a crucial role in data operations, such as select,delete, update, and insert, because without it there is no way to know whichrow is being modified or selected. The XPath data model uses a concept known ashierarchical or location path to uniquely locate or identify a node in the treehierarchy. The hierarchical or location paths play the same role in a treehierarchy that primary keys play in a tabular representation. As Figure 2 shows, every node in the tree is the root nodeof yet another tree unless the node is a leaf node. This means the tree is ahierarchy of trees where each tree is built out of smaller trees. The path of anode in a tree hierarchy uniquely identifies and locates not only the nodeitself but also the sub tree associated with the node. The primary key of a row is normally an autogeneratedinteger number with a unique value. The hierarchical or location path of anode, on the other hand, is built out of the location steps of its ancestornodes all the way up to the root node of the entire tree hierarchy. Thehierarchical path of a node is based on an imaginary journey from the root nodeof the tree all the way down to the node itself. The journey consists ofseveral location steps. Each location step takes us from the node where we arecurrently to the next node. Let s consider an example: Suppose we want tolocate the gray node (Message) shown in Figure 2. Our journey begins at the root node of the entire treehierarchy. The XPath data model uses the notation / to represent the rootnode. The first location step: Messages[position=1] takes us from the root node to the Messages node. So farthe location path is: /Messages[position=1] The second location step: Message[position=1] takes us from the Messages node to the first Message node.The location path is so far then: /Messages[position=1]/Message[position=1] The third location step: Message[position=1] takes us from the current Message node to the next Messagenode. The location path is now: /Messages[position=1]/Message[position=_ 1]/Message[position=1] The final location step: Message[position=1] takes us to our destination, i.e. the gray node. Therefore,the location path of the gray node is as follows: /Messages[position()=1]/Message[position()=_ 1]/Message[position()=1]/Message[position()=1] As the example shows, the location path of a node uniquelyidentifies and locates the node and its associated sub tree in the treehierarchy. The XmlDataSource control provides hierarchical data-boundcontrols such as TreeView and Menu with the hierarchical views of theunderlying XML document. A hierarchical view represents a particular sub treein the in-memory tree representation of the document. Therefore, thehierarchical path of the root node of a sub tree uniquely identifies thehierarchical view that represents the sub tree. That is why the hierarchicalpath of the root node of a sub tree is also referred to as a view path. Everyhierarchical view has a unique view path. To make our discussion more concrete, let s examine theuser interface of the threaded discussion forum application more closely, asshown in Figure 3.
Figure 3: The XML-based threadeddiscussion forum. The user interface consists of a TreeView and aDetailsView control. The TreeView control displays the subject, added date, anduser name of all the message nodes of the tree hierarchy. The TreeView andDetailsView controls create a master/detail form where the user selects amessage from the TreeView control to see its details in the DetailsViewcontrol. The DetailsView control also allows authorized users to edit, delete,or reply to the selected message or start a new thread of discussion. The DetailsView control, therefore, does not display,edit, delete, or reply to all the message nodes of the tree. It only displays,edits, deletes, or replies to the message node that the user selected from theTreeView control. This means the DetailsView control must first locate theselected message node in the underlying tree representation. The only way tolocate a node in a tree is to find out its hierarchical or location path. Let ssee how the DetailsView control accesses the hierarchical path of the selectedmessage. The TreeView control creates an instance of the TreeNodeclass for each message node it displays and sets its DataPath property to thehierarchical or location path of the message node. When the user selects amessage from the TreeView control, the SelectedNode property of the control isset to the TreeNode object that represents the selected message node. Thereforethe DetailsView control can easily use the DataPath property of theSelectedNode object of the TreeView control to access the hierarchical path ofthe selected message node, i.e. TreeView1.SelectedNode.DataPath. One of the responsibilities of the DetailsView control isto use the hierarchical path of the selected message node to locate the node inthe underlying tree representation, extract its details, and display them tousers. Thanks to the new ASP.NET 2.0 data source and data-bound model, this isall done automatically. All a page developer needs to do is to set the XPathproperty of the XmlDataSource associated with the DetailsView control to thehierarchical path of the selected message node. This can easily be done in thecallback for the SelectedNodeChanged event of the TreeView control: void SelectedNodeChanged(object sender, EventArgs e) { MySource2.XPath =TreeView1.SelectedNode.DataPath; if (dv.CurrentMode !=DetailsViewMode.ReadOnly) dv.ChangeMode(DetailsViewMode.ReadOnly); } Setting the XPath property of the XmlDataSource controlassociated with the DetailsView control (i.e. MySource2) to the hierarchicalpath of the selected message node is all it takes to have the DetailsViewcontrol extract the details of the selected message node from the tree anddisplay them. Let s see what makes this possible. The DetailsView control internally registers a callbackfor the DataSourceChanged event of its associated XmlDataSource control, i.e.MySource2. The XmlDataSource control raises the event when: 1) Oneor more of its properties change value. 2) Theunderlying data store changes because of a Delete, Update, or Insert operation. Therefore, setting the XPath property of the XmlDataSourcecontrol raises the DataSourceChanged event and calls the internal callbackfunction where the DetailsView control uses the XmlDataSource control toautomatically extract the details of the selected message node from theunderlying tree and displays them to users. The great thing about the DetailsView control is that itallows all operations, i.e. display, edit, delete, and reply, and adds a newthread to be handled within the same server control, i.e. the DetailsViewcontrol. Switching from one operation to another is done via switching the modeof the DetailsView control. The DetailsView control can be in one of the threepossible modes, i.e. DetailsViewMode.ReadOnly, DetailsViewMode.Edit, andDetailsViewMode.Insert. When the user selects a message from the TreeView control,the DetailsView control is switched to the DetailsViewMode.ReadOnly mode wherethe details of the selected message are displayed. When the user clicks theEdit button of the DetailsView control, the DetailsView control is switched tothe DetailsViewMode.Edit mode, where the user can edit the selected message.When the user clicks the Reply button of the DetailsView control, theDetailsView control is switched to the DetailsViewMode.Insert mode, where theuser can reply to the selected message. When the user clicks the NewThreadbutton, the DetailsView control is switched to the DetailsViewMode.Insert mode,where the user can start a new thread. Displaying All Messages The TreeView control uses the following XmlDataSourcecontrol to extract all the message nodes from the tree: EnableCaching="true" CacheDuration="300" CacheExpirationPolicy="Sliding"CacheKeyDependency="MyKey" DataFile="messages.xml"XPath="/Messages/Message" /> The XPath property operates like the SelectCommand of theSqlDataSource control, i.e. it specifies which message nodes will be selected.In this case, it s set to the value /Messages/Message to extract all themessage nodes. Accessing the underlying data store is one of the mosttime-consuming operations in data-driven Web applications. Page developersnormally cache data query results in the Cache object to improve theperformance. The XmlDataSource control allows page developers to cache datawithout writing a single line of code. All they have to do is set theEnableCaching, CacheDuration, and CacheExpirationPolicy properties of theXmlDataSource control. The possible values of CacheExpirationPolicy are Slidingand Absolute. Automatic caching is possible because the XmlDataSourcecontrol uses W3C DOM APIs to load the entire XML document into memory. Thestreaming load model, on the other hand, does not allow caching because onlythe current node is kept in memory. The downside of caching is the problem of stale data. Thisproblem occurs when the underlying data store changes but the application stilldisplays out of date information. Like any other ASP.NET component, theXmlDataSource control uses the Insert method of the Cache object to cache thequery results. The Insert method takes three arguments. The first argumentspecifies the key under which the data is cached. The key is later used toaccess the cached data. The XmlDataSource control exposes a public propertynamed CacheKeyDependency. The control caches the data under the key that pagedevelopers specify as the value of this property. We ll see later that the callbacks for the Delete, Update,and Edit operations in the DetailsView control call the Remove method of theCache object to invalidate the data cached under the key specified in theCacheKeyDependency property. The next time the page is accessed theXmlDataSource control will extract fresh data from the underlying XML document.This automatically resolves the problem of stale data. The application also registers the DataBound method as thecallback for the TreeNodeDataBound event of the TreeView control, where itspecifies what information to display for each message: void DataBound(Object sender, TreeNodeEventArgs e) { if(((XmlNode)e.Node.DataItem).LocalName == "Message") e.Node.Text =XPathBinder.Eval(e.Node.DataItem, "Subject").ToString() + ", by " + XPathBinder.Eval(e.Node.DataItem, "@UserName").ToString() + " " + XPathBinder.Eval(e.Node.DataItem, "@AddedDate").ToString();} The Eval method of the XPathBinder takes two arguments.The first argument is the object against which a given XPath expression isevaluated. The second argument is the XPath expression being evaluated. Thefirst argument only accepts objects whose classes implement the IXPathNavigableinterface. This is because the Eval method simply calls the CreateNavigatormethod of the object to access its XPathNavigator object. The Eval method thencalls the Select method of the XPathNavigator object and passes the XPathexpression as its argument. Let s take a look at the XPath expressions used as thesecond arguments of the Eval method calls, i.e. Subject, @UserName, and@AddedDate. These expressions refer to the child element andUserName and AddedDate attributes of the selected message node. As shown in Figure2, the child element and UserName and AddedDate attributes arethemselves nodes of the tree hierarchy. Therefore, the XPath expressions arenothing but the location steps that take us from the selected message node tothe Subject, UserName, and AddedDate nodes. The Select method of theXPathNavigator object uses these location steps to locate these nodes andreturn references to them. Displaying the Details of a Message Because the DetailsView control is bound to anXmlDataSource control where every data item implements the IXPathNavigableinterface, it uses XPathBinder in its data-binding expressions. XPath is theshort version of XPathBinder.Eval(Container.DataItem, xpathexpression, format).The DetailsView control uses four XPath data-binding expressions: 1) XPath( Subject/text )returns the subject of the selected message node. The text function returns thetext within the opening and closing tags of the element in theXML document. As Figure 2 shows, the text itself is a node in the treehierarchy. The XPath expression Subject/text is therefore a location paththat takes us from the selected message node to the text node. 2) XPath( Body/text ) returns the body of the selected message node. 3) XPath( @AddedDate ) returns the value of the AddedDate attribute of the selected element. As Figure 2 shows, the attribute itself is a node. 4) XPath( @UserName ) returns the value of the UserName attribute of the selected element. The DetailsView control and its associated XmlDataSourcecontrol work together to automatically display the details of the message nodethat the user selects from the TreeView control. In other words, the selectoperation is done automatically. However, XmlDataSource does not provideautomatic support for delete, update, and insert operations; the applicationmust explicitly handle these operations. Deleting a Message The ItemTemplate section of the DetailsView controlcontains the delete button. The DetailsView control provides built-in supportfor deleting items. Page developers only need to add a new delete button to theItemTemplate section and set its CommandName property to Delete . When theuser clicks the Delete button, the DetailsView control checks the value of theCanDelete property of its associated view object. If it is true, the controlcalls the Delete method of the view object; otherwise, it throws an exception.The CanDelete property value is true only when the view object implements theDelete method. However, the XmlDataSourceView class does not implementthe Delete method. Therefore, the application must not set the CommandNameproperty of the delete button to the value Delete , otherwise an exceptionwould be thrown when the button is clicked. The application sets theCommandName property of the delete button to the value SubmitDelete insteadand registers the DetailsView_ItemCommand method as the callback for theItemCommand event of the DetailsView control to handle the delete event. Later,we ll see that the DetailsView_ItemCommand method will also be used to handlethe update and insert events: void DetailsView_ItemCommand(object sender, DetailsViewCommandEventArgs e) { switch (e.CommandName) { case"SubmitUpdate": Update(); break; case "SubmitInsert": Insert(); break; case"SubmitDelete": Delete(); break; } } The method calls the Delete method to handle the deleteevent: void Delete(){ XmlDocument doc =MySource2.GetXmlDocument(); String dataPath = TreeView1.SelectedNode.DataPath; XmlNode message =doc.SelectSingleNode(dataPath); message.ParentNode.RemoveChild(message); MySource2.XPath =""; Save();} As previously discussed, the XmlDataSource control usesthe W3C DOM APIs to load the entire messages.xml file into memory, and createsan in-memory tree representation of the XML document. The great thing about theW3C DOM model is that it allows page developers to add, update, and deletenodes from the in-memory tree. The XmlDataSource control exposes a method namedGetXmlDocument that returns a reference to the underlying XmlDocument object. Deleting a node from the tree hierarchy involves thefollowing four steps: 1) Findout the hierarchical path of the node to be deleted. Because the message nodebeing deleted is the node that the user selected from the TreeView control, thevalue of the DataPath property of the SelectedNode of the TreeView control isthe hierarchical path of the node being deleted. 2) Callthe SelectSingleNode method of the XmlDocument object and pass the hierarchicalpath of the node as its argument. The method uses the hierarchical path tolocate the message node in the tree XmlNode message =doc.SelectSingleNode(TreeView1.Selected.DataPath); 3) Accessthe parent node of the node being deleted, XmlNode parent = message.ParentNode; 4) Callthe RemoveChild method of the parent node to delete the node from the tree, parent.RemoveChild(message); The Delete method then calls the Save method: void Save(){ MySource2.Save(); if (DetailsView1.CurrentMode!= DetailsViewMode.ReadOnly) DetailsView1.ChangeMode(DetailsViewMode.ReadOnly); Cache.Remove("MyKey"); TreeView1.DataBind();} The Save method takes care of the following issues: 1) Removingthe selected message node from the in-memory tree hierarchy does notautomatically remove the message from the underlying data store, i.e. XMLdocument. The Save method calls the Save method of the associated XmlDataSourcecontrol to propagate the changes to the XML document. 2) Recallthe XmlDataSource control associated with the TreeView control caches its queryresults in the Cache object under the key specified in its CacheKeyDependencyproperty. Because the Delete method changes the underlying data store, it mustcall the Remove method of the Cache object to invalidate the cached data;otherwise, the TreeView control will show out of date data. 3) TheDataBind method of the TreeView control must be called to update the TreeViewcontrol display. Because the cached data has already been invalidated, the DataBindmethod will extract fresh data from the underlying XML document. 4) TheDetailsView control must be switched back to its ReadOnly mode. Updating a Message The ItemTemplate section of the DetailsView controlcontains the edit button. Because the CommandName property of the button is setto Edit , when the user clicks the button, the DetailsView controlautomatically switches to DetailsViewMode.Edit mode where it renders thecontents of its EditItemTemplate section including the Update and Cancel buttons. When the Cancel button is clicked, the DetailsView controlautomatically switches back to the DetailsViewMode.ReadOnly mode where itrenders the contents of its ItemTemplate section. Notice the CommandNameproperty of the Update button is not set to Update for the same reason thatthe CommandName property of the Delete button was not set to Delete . Theapplication sets the property to SubmitUpdate and uses theDetailsView_ItemCommand method to handle the event. The method calls the Updatemethod to handle the Update event (see Figure 4). void Update(){ TextBox subject1 =(TextBox)DetailsView1.FindControl("EditSubject"); TextBox body1 =(TextBox)DetailsView1.FindControl("EditBody"); XmlDocument doc =MySource2.GetXmlDocument(); string subjectPath =TreeView1.SelectedNode.DataPath + "/Subject"; XmlNode subject =doc.SelectSingleNode(subjectPath); subject.InnerText =subject1.Text; string bodyPath =TreeView1.SelectedNode.DataPath + "/Body"; XmlNode body =doc.SelectSingleNode(bodyPath ); body.InnerText =body1.Text; Save();}Figure 4: TheDetailsView_ItemCommand method calls the Update method to handle the Updateevent. The Update method first extracts the new values for thesubject and body of the selected message. To update a node in the treehierarchy, first find out the hierarchical path of the node to be updated.Because the message node being updated is the message that the user selectedfrom the TreeView control, the value of the DataPath property of theSelectedNode of the TreeView control is the hierarchical path of the messagenode. However, we want to update the child nodes (i.e. subject and body nodes)of the message node, not the message node itself. Recall the hierarchical pathof a node takes us from the root node of the tree, node by node, all the waydown to the node itself. The hierarchical path consists of location steps whereeach location step takes us from the node where we are currently to the nextnode. This means we need to add another location step to the hierarchical pathof the message node to go from the message node to its child nodes, i.e.subject and body nodes. Therefore the hierarchical paths of the subject andbody nodes are: string subjectPath = TreeView1.SelectedNode.DataPath + "/Subject"; sring bodyPath = TreeView1.SelectedNode.DataPath +"/Body"; Next, call the SelectSingleNode method of the XmlDocumentobject and pass the hierarchical path of the node to access the node in thetree: XmlNode subject = doc.SelectSingleNode(subjectPath); XmlNode body = doc.SelectSingleNode(bodyPath); Then update the node: subject.InnerText = subject1.Text; body.InnerText = body1.Text; Notice the SelectSingleNode method returns the referenceto the actual node in the tree. This allows us to directly update theproperties of the subject and body nodes. At the end, the Update method doesexactly what the Delete method did; that is, it calls the Save method. Replying to a Message The ItemTemplate property of the DetailsView controlcontains the Reply button. Because the CommandName property of the button isset to New, when the user clicks the button, the DetailsView controlautomatically switches to the DetailsViewMode.Insert mode where the controlrenders the contents of its InsertItemTemplate section that also includes theInsert button. Notice the CommandName property of the Insert button isnot set to Insert for the same reason that the CommandName properties of theDelete and Update buttons were not set to Delete and Update . Theapplication sets the property to SubmitInsert and uses theDetailsView_ItemCommand method to handle the event. The method calls the Insertmethod to handle the Insert event. Figure 5 shows the code for the Insertmethod. void Insert(){ TextBox subject1 =(TextBox)DetailsView1.FindControl("InsertSubject"); TextBox body1 =(TextBox)DetailsView1.FindControl("InsertBody"); XmlDocument doc =MySource2.GetXmlDocument(); XmlElement message =doc.CreateElement("Message"); XmlNode parent; if(ViewState["NewThread"] == null) parent =doc.SelectSingleNode(TreeView1.SelectedNode.DataPath); else { ViewState.Remove("NewThread"); parent =doc.DocumentElement; } parent.AppendChild(message); message.SetAttribute("AddedDate", DateTime.Now.ToShortDateString()); message.SetAttribute("UserName", User.Identity.Name); XmlElement subject =doc.CreateElement("Subject"); message.AppendChild(subject); subject.InnerText =subject1.Text; XmlElement body =doc.CreateElement("Body"); message.AppendChild(body); body.InnerText =body1.Text; Save();}Figure 5: TheInsert method is used to reply to the selected message or start a new thread. Adding a new element node to the tree hierarchy involvesthe following six steps: 1) Callthe CreateElement method of the XmlDocument object to create the new elementnode. 2) Setthe properties of the new element node. 3) Callthe SetAttribute method of the new element node to set its attributes. 4) Findout the hierarchical path of the element node that will act as the parent nodeof the new element node. 5) Callthe SelectSingleNode method of the XmlDocument object and pass the hierarchicalpath of the parent node as its argument to access the parent node in the tree. 6) Callthe AppendChild method of the parent node to add the new element node to thetree as its child node. The Insert method creates three element nodes and addsthem to the tree hierarchy. The first element node represents the reply messageitself. The second and third element nodes represent the subject and body ofthe reply message. The Insert method follows the previously mentioned six stepsfor each element node that it creates and adds to the tree hierarchy. Forinstance, let s consider the six steps for the creation and addition of theelement node that represents the reply message itself: 1) Createthe element node, XmlElement message = doc.CreateElement( Message ); 2) Notapplicable 3) Becausethe message element exposes two attributes, we must call the SetAttributemethod twice: message.SetAttribute( AddedDate ,DateTime.Now.ToShortDateString); and message.SetAttribute( UserName ,User.Identity.Name); 4) Becausethe message node being added is the reply to the message node that the userselected from the TreeView control, the selected message node will be the parentof the new message node. Therefore, the value of the DataPath property of theSelectedNode of the TreeView control is the hierarchical path of the parentnode of the new element node. 5) Accessthe parent element node in the tree hierarchy, XmlNode parent =doc.SelectSingleNode(TreeView1.SelectedNode.DataPath); 6) Addthe new element node to the tree hierarchy as the child node of the parent node,parent.AppendChild(message); At the end, the Insert method calls the Save method tocommit all the changes to the disk and update the TreeView and DetailsViewcontrols. Starting a New Thread The NewThreadClick method is registered as the callbackfor the Click event of the NewThread button: void NewThreadClick(object sender, EventArgs e) { DetailsView1.ChangeMode(DetailsViewMode.Insert); ViewState["NewThread"] = "NewThread"; } The method calls the ChangeMode method of the DetailsViewcontrol to change its mode to DetailsViewMode.Insert where the control rendersthe contents of its InsertItemTemplate property. The method also stores NewThread in ViewState under the key NewThread . Because both replying to a message and creating a newthread switch the DetailsView control to its Insert mode, the same discussionspresented in the previous section apply equally to this section. The onlydifference is that the Insert method appends the newly created message node asthe child node of the document element because it starts a new thread. TheInsert method uses ViewState[ NewThread ] as the signal to find out whether theuser is starting a new thread or replying to an existing message. Conclusion This article presents the implementation of an XML-basedthreaded discussion forum that uses new ASP.NET 2.0 controls such asXmlDataSource, TreeView, and DetailsView and an XML document as its data store.The TreeView and DetailsView controls create master/detail views of messages.Selecting a message from the TreeView control displays its details in theDetailsView control where the user can also update, delete, and reply to themessage or start a new thread. The XmlDataSource control does not provide built-insupport for Update, Delete, and Insert data operations. This articledemonstrates how to use the underlying XmlDocument object and the classes inthe System.Xml namespace to handle Update, Delete, and Insert operations. This article uses the XPath location path of a messagenode as its unique identifier. The unique identifiers are used in Update,Delete, or Reply operations to identify the message node being updated, deleted,or replied to. The sample code accompanyingthis article is available for download. Dr. Shahram Khosraviis a Senior Software Engineer with Schlumberger Information Solutions (SIS).Shahram specializes in ASP.NET 1.x/2.0, XML Web services, .NET 1.x/2.0technologies, XML technologies, ADO.NET 1.x/2.0, 3D Computer Graphics,HI/Usability, and Design Patterns. Shahram has extensive expertise indeveloping ASP.NET 1.x/2.0 custom server controls and components. He has morethan 10 years of experience in object-oriented programming. He uses a varietyof Microsoft tools and technologies such as SQL Server 2000 and 2005. Shahramhas written articles on .NET 1.x/2.0 and ASP.NET 1.x/2.0 technologies for asp.netPRO magazine, Microsoft MSDN Online,and CoDe magazine. Reach him at mailto:[email protected].
About the Author
You May Also Like