using System;
using System.Xml;
using System.IO;
namespace DevComponents.Tree
{
///
/// Provides means for TreeGX serialization.
///
public class TreeSerializer
{
#region Private Variables
private static string XmlNodeName="Node";
private static string XmlCellsName="Cells";
private static string XmlCellName="Cell";
private static string XmlCellImagesName="Images";
private static string XmlTreeGXName="TreeGX";
private static string XmlCustomName = "Custom";
#endregion
#region Saving
///
/// Saves Nodes to specified file.
///
/// TreeGX to save
/// Target file name
public static void Save(TreeGX tree, string fileName)
{
XmlDocument document=Save(tree);
document.Save(fileName);
}
///
/// Saves Nodes to stream.
///
/// TreeGX to save
/// Stream to save nodes to.
public static void Save(TreeGX tree, Stream outStream)
{
XmlDocument document=Save(tree);
document.Save(outStream);
}
///
/// Saves Nodes to TextWriter
///
/// TreeGX to save
/// TextWriter to write nodes to.
public static void Save(TreeGX tree, TextWriter writer)
{
XmlDocument document=Save(tree);
document.Save(writer);
}
///
/// Saves nodes to XmlWriter.
///
/// TreeGX to save
/// XmlWriter to write nodes to
public static void Save(TreeGX tree, XmlWriter writer)
{
XmlDocument document=Save(tree);
document.Save(writer);
}
///
/// Creates new XmlDocument and serializes TreeGX into it.
///
/// TreeGX to serialize
/// New instance of XmlDocument/returns>
public static XmlDocument Save(TreeGX tree)
{
XmlDocument document=new XmlDocument();
Save(tree, document);
return document;
}
///
/// Saves TreeGX to an existing XmlDocument. New node TreeGX is created in document and Nodes are serialized into it.
///
/// TreeGX to serialize
/// XmlDocument instance.
public static void Save(TreeGX tree, XmlDocument document)
{
XmlElement parent = document.CreateElement(XmlTreeGXName);
document.AppendChild(parent);
TreeSerializer.Save(tree, parent);
}
///
/// Serializes TreeGX object to XmlElement object.
///
/// Instance of TreeGX to serialize.
/// XmlElement to serialize to.
public static void Save(TreeGX tree, XmlElement parent)
{
NodeSerializationContext context = new NodeSerializationContext();
context.RefXmlElement = parent;
context.TreeGX = tree;
context.HasSerializeNodeHandlers = tree.HasSerializeNodeHandlers;
context.HasDeserializeNodeHandlers = tree.HasDeserializeNodeHandlers;
foreach(Node node in tree.Nodes)
{
Save(node, context);
}
}
///
/// Serializes Node and all child nodes to XmlElement object.
///
/// Node to serialize.
/// Provides serialization context.
public static void Save(Node node, NodeSerializationContext context)
{
XmlElement parent = context.RefXmlElement;
XmlElement xmlNode=parent.OwnerDocument.CreateElement(XmlNodeName);
parent.AppendChild(xmlNode);
ElementSerializer.Serialize(node, xmlNode);
if(node.Cells.Count>1)
{
XmlElement xmlCells = parent.OwnerDocument.CreateElement(XmlCellsName);
xmlNode.AppendChild(xmlCells);
for(int i=1; i 0 || customXml.ChildNodes.Count > 0)
xmlNode.AppendChild(customXml);
}
context.RefXmlElement = xmlNode;
foreach(Node childNode in node.Nodes)
{
Save(childNode, context);
}
context.RefXmlElement = parent;
}
#endregion
#region Loading
///
/// Load TreeGX Nodes from file.
///
/// Reference to TreeGX to populate
/// File name.
public static void Load(TreeGX tree, string fileName)
{
XmlDocument document=new XmlDocument();
document.Load(fileName);
Load(tree, document);
}
///
/// Load TreeGX Nodes from stream.
///
/// Reference to TreeGX to populate
/// Reference to stream
public static void Load(TreeGX tree, Stream inStream)
{
XmlDocument document=new XmlDocument();
document.Load(inStream);
Load(tree, document);
}
///
/// Load TreeGX Nodes from reader.
///
/// Reference to TreeGX to populate
/// Reference to reader.
public static void Load(TreeGX tree, TextReader reader)
{
XmlDocument document=new XmlDocument();
document.Load(reader);
Load(tree, document);
}
///
/// Load TreeGX Nodes from reader.
///
/// Reference to TreeGX to populate
/// Reference to reader.
public static void Load(TreeGX tree, XmlReader reader)
{
XmlDocument document=new XmlDocument();
document.Load(reader);
Load(tree, document);
}
///
/// Load TreeGX from XmlDocument that was created by Save method.
///
/// Tree Control to load
/// XmlDocument to load control from
public static void Load(TreeGX tree, XmlDocument document)
{
foreach(XmlNode xmlNode in document.ChildNodes)
{
if(xmlNode.Name==XmlTreeGXName && xmlNode is XmlElement)
{
Load(tree, xmlNode as XmlElement);
break;
}
}
}
///
/// Load nodes from XmlElement.
///
/// Reference to TreeGX to be populated.
/// XmlElement that tree was serialized to.
public static void Load(TreeGX tree, XmlElement parent)
{
tree.BeginUpdate();
tree.DisplayRootNode = null;
tree.Nodes.Clear();
NodeSerializationContext context = new NodeSerializationContext();
context.TreeGX = tree;
context.HasDeserializeNodeHandlers = tree.HasDeserializeNodeHandlers;
context.HasSerializeNodeHandlers = tree.HasSerializeNodeHandlers;
try
{
foreach(XmlNode xmlNode in parent.ChildNodes)
{
if(xmlNode.Name==XmlNodeName && xmlNode is XmlElement)
{
Node node=new Node();
tree.Nodes.Add(node);
context.RefXmlElement = xmlNode as XmlElement;
LoadNode(node, context);
}
}
}
finally
{
tree.EndUpdate();
}
}
///
/// Load single node and it's child nodes if any.
///
/// New instance of node that is populated with loaded data.
/// Provides deserialization context.
public static void LoadNode(Node nodeToLoad, NodeSerializationContext context)
{
XmlElement xmlNode = context.RefXmlElement;
ElementSerializer.Deserialize(nodeToLoad, xmlNode);
foreach(XmlNode xmlChild in xmlNode.ChildNodes)
{
XmlElement xmlElem = xmlChild as XmlElement;
if(xmlElem == null)
continue;
if(xmlElem.Name==XmlNodeName)
{
Node node=new Node();
nodeToLoad.Nodes.Add(node);
context.RefXmlElement = xmlElem;
LoadNode(node, context);
}
else if(xmlElem.Name == XmlCellsName)
{
LoadCells(nodeToLoad, xmlElem);
}
else if(xmlElem.Name == XmlCustomName)
{
if(context.HasDeserializeNodeHandlers)
{
SerializeNodeEventArgs e = new SerializeNodeEventArgs(nodeToLoad, xmlNode, xmlElem);
context.TreeGX.InvokeDeserializeNode(e);
}
}
}
context.RefXmlElement = xmlNode;
}
private static void LoadCells(Node parentNode, XmlElement xmlCells)
{
foreach(XmlNode xmlChild in xmlCells.ChildNodes)
{
if(xmlChild.Name==XmlCellName && xmlChild is XmlElement)
{
Cell cell=new Cell();
parentNode.Cells.Add(cell);
ElementSerializer.Deserialize(cell, xmlChild as XmlElement);
// Load images if any
foreach(XmlElement xmlImage in xmlChild.ChildNodes)
{
if(xmlImage.Name==XmlCellImagesName)
{
ElementSerializer.Deserialize(cell.Images, xmlImage);
break;
}
}
}
}
}
#endregion
}
///
/// Provides context information for serialization.
///
public class NodeSerializationContext
{
///
/// Gets or sets reference to context parent XmlElement when serializing or actual Node element when deserializing.
///
public System.Xml.XmlElement RefXmlElement = null;
///
/// Gets or sets whether SerializeNode event handler has been defined and whether event should be fired.
///
public bool HasSerializeNodeHandlers = false;
///
/// Gets or sets whether DeserializeNode event handler has been defined and whether event should be fired.
///
public bool HasDeserializeNodeHandlers = false;
///
/// Provides access to serializer.
///
public TreeGX TreeGX = null;
}
}