using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; class Program { private class ChangedSemaphore { } private static EventHandler ElementChanged = new EventHandler(Program.ElementChangedHandler); private static void ElementChangedHandler(object sender, XObjectChangeEventArgs e) { XObject xSender = (XObject)sender; XDocument xDocument = xSender.Document; // Sometimes while moving a node, we may receive an event for a node that has been // removed from its parent (and therefore its document). This removed node will receive // an event, and its parent document will be null. In this case, we don't care // about removing the event handler and adding an annotation. The document will receive // another event for the parent of the removed node, which will cause the semaphore // annotation to be added to the parent XDocument. if (xDocument != null) { xDocument.Changing -= ElementChanged; xDocument.Changed -= ElementChanged; xDocument.AddAnnotation(new ChangedSemaphore()); } } static void Main(string[] args) { // load a very large, complicated XDocument for which we want to track change status. XDocument doc = XDocument.Parse( @" 1 2 3 "); // add event handlers to the document so that any changes will be noted doc.Changing += ElementChanged; doc.Changed += ElementChanged; // // // // execute a bunch of code that may or may not change the XDocument // (in this case, we'll not change the XDocument) // // // if (doc.Annotation() != null) Console.WriteLine("XDocument has changed"); else Console.WriteLine("XDocument has not changed"); // // // // execute a bunch of code that may or may not change the XDocument // (in this case, we'll change the value of the first element) doc.Root.Element("Child").Value = "5"; // // // if (doc.Annotation() != null) Console.WriteLine("XDocument has changed"); else Console.WriteLine("XDocument has not changed"); } }