Save a diagram

Feb 3, 2012 at 4:21 PM


1. What is the code to save a diagram? I tried:

    Dim d As New Crainiate.Diagramming.Document(Me.Diagram1.Model)


but I got ArgumentException:

An item with the same key has already been added.

in line 65 of custombinder.cs

Feb 3, 2012 at 4:23 PM

ok I see this issue reported.

Any help would be appreciated.

Feb 3, 2012 at 4:36 PM
Edited Feb 3, 2012 at 4:36 PM

See the issue- I may have fixed this.

Now I am going to see if I can get xml formatter support added.

What I'm thinking is this:

If I serialize a totally unrelated object model to xml, I can use xslt to transform it into an xmldocument that diagram can open.

I have non-diagram data I want represented on a diagram. Needs to be two-way back and forth.

Want to use the diagram to edit the unrelated object model, in other words.

I guess I could write code to loop thru my object model and add shapes but xslt seems more better for some reason to me.

Feb 3, 2012 at 4:58 PM

Well I got that working by changing Document.cs as follows:



        //Saves a diagram in xml or binary format to the filename provided.        public virtual void Save(string path, System.Data.SerializationFormat format = System.Data.SerializationFormat.Binary)        {            using (Stream stream = new FileStream(path, FileMode.Create))            {                Save(stream, format);                stream.Close();            }        }
        //Saves a diagram in xml or binary format to the stream provided.        public virtual void Save(Stream stream, System.Data.SerializationFormat format = System.Data.SerializationFormat.Binary)        {            switch( format)            {                case System.Data.SerializationFormat.Binary:                    CreatePackage(stream);                    break;                case System.Data.SerializationFormat.Xml:                    //Serialize the model into the part stream                    XmlFormatter formatter = Formatter;                    formatter.Shallow = false;                    formatter.Serialize(stream, Model);                    break;            }        }

I'm sorry about no code block. That was not functioning in my browser right for some reason today.
Anyways, this works the way I expected; however, I DON'T know C# and I DON'T know what I'm doing, so if I missed part of the document or part structure lemme know! Thanks!

Feb 15, 2012 at 10:15 AM


//To save to xml
using (FileStream fs = new FileStream(_filename, mode, FileAccess.Write))
    myDiagram.Save(fs, SaveFormat.Xml); //Important method
    byte[] name_bytes = ASCIIEncoding.ASCII.GetBytes(filename);
    fs.Write(name_bytes, 0, name_bytes.Length);
    byte[] position_bytes = BitConverter.GetBytes(whatever you want);
    fs.Write(position_bytes, 0, position_bytes.Length);

//To load xml
System.IO.FileStream stream = new System.IO.FileStream(
myDiagram.Open(stream, LoadFormat.Xml);

Feb 23, 2012 at 10:02 AM

I have saved the diagram to XML but I am having a problem reloading it from XML. I created  an Open(path,format) method that calls another Open(stream,format) that deserialize  the stream. However the diagram is not showing on the control. What am i doing wrong? Thank you in advance

Below is the code I am using in the Document.cs

 public virtual void LoadDiagram(string path, System.Data.SerializationFormat format = System.Data.SerializationFormat.Binary)
            using (Stream stream = new FileStream(path, System.IO.FileMode.Open,System.IO.FileAccess.Read))
                Open(stream, format);

        public virtual void Open(Stream stream, System.Data.SerializationFormat format = System.Data.SerializationFormat.Binary)
            switch (format)
                case System.Data.SerializationFormat.Binary:
                case System.Data.SerializationFormat.Xml:
                    //Serialize the model into the part stream       
                    XmlFormatter formatter = Formatter;
                    formatter.Shallow = false;

and this is what I do on the Main form

            Document myDiagram = new Document(this.diagram1.Controller.Model);
            myDiagram.LoadDiagram(path, System.Data.SerializationFormat.Xml);

Feb 23, 2012 at 1:21 PM
Edited Feb 23, 2012 at 1:22 PM

The way to troubleshoot is to start with the simplest diagram possible (an empty one) and save, load, and inspect the properties before and after the save/load.

Then add one element, etc. until you find the property (or object that has been added, removed or changed).

Also be sure to set your debugger to break on Throw, not on unhandled.

I actually went another route and I build my diagram on the fly from my object model without persistance. I persist my object model elsewhere not in diagram format but to Sql Server. So I abandoned this approach.

However I know if you want to preserve the human created layout of a diagram to xml this is a problem someone needs to solve.

I'm actually in the middle of a project and I can't divert from my tasks right now. Sorry.

May 29, 2012 at 2:20 PM
Edited May 29, 2012 at 2:21 PM

Are there plans to add ISerializationSurrogate classes for tables?

May 30, 2012 at 6:58 AM

By serializing the Table element am guessing you want to save this element.

I managed to work around it this way:

public class TableSerializer : ElementSerialize
        public override void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
            base.GetObjectData(obj, info, context);

            Table table = (Table)obj;

            info.AddValue("BackColor", table.BackColor.ToArgb().ToString());
            info.AddValue("Clip", table.Clip);
            info.AddValue("GradientMode", Convert.ToInt32(table.GradientMode).ToString());
            info.AddValue("GradientColor", table.GradientColor.ToArgb().ToString());
            info.AddValue("DrawGradient", table.DrawGradient);
            info.AddValue("DrawBorder", table.DrawBorder);
            info.AddValue("DrawBackground", table.DrawBackground);
            info.AddValue("Location", Serialize.AddPointF(table.Location));
            info.AddValue("InternalRectangle", Serialize.AddRectangleF(table.InternalRectangle));
            info.AddValue("Rotation", table.Rotation);
            info.AddValue("Label", table.Label, typeof(Label));
            info.AddValue("Image", table.Image, typeof(Image));
            info.AddValue("StencilItem", table.StencilItem, typeof(StencilItem));
            info.AddValue("AllowMove", table.AllowMove);
            info.AddValue("AllowSnap", table.AllowSnap);
            info.AddValue("AllowScale", table.AllowScale);
            info.AddValue("AllowRotate", table.AllowRotate);
            info.AddValue("DrawSelected", table.DrawSelected);
            info.AddValue("Selected", table.Selected);
            info.AddValue("KeepAspect", table.KeepAspect);
            info.AddValue("MinimumSize", Serialize.AddSizeF(table.MinimumSize));
            info.AddValue("MaximumSize", Serialize.AddSizeF(table.MaximumSize));
            info.AddValue("Direction", Convert.ToInt32(table.Direction).ToString());
            info.AddValue("Interaction", Convert.ToInt32(table.Interaction).ToString());
            info.AddValue("Ports", table.Ports);

        public override object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
            base.SetObjectData(obj, info, context, selector);

            Table table = (Table)obj;
            SerializationInfoEnumerator enumerator = info.GetEnumerator();
            foreach(var item in info)
                if (item.Name == "BackColor") table.BackColor = Color.FromArgb(Convert.ToInt32(info.GetString("BackColor")));
                if (item.Name == "Clip") table.Clip = info.GetBoolean("Clip");
                if (item.Name == "GradientMode") table.GradientMode = (LinearGradientMode)Enum.Parse(typeof(LinearGradientMode), info.GetString("GradientMode"), true);
                if (item.Name == "GradientColor") table.GradientColor = Color.FromArgb(Convert.ToInt32(info.GetString("GradientColor")));
                if (item.Name == "DrawGradient") table.DrawGradient = info.GetBoolean("DrawGradient");
                if (item.Name == "DrawBorder") table.DrawBorder = info.GetBoolean("DrawBorder");
                if (item.Name == "DrawBackground") table.DrawBackground = info.GetBoolean("DrawBackground");
                if (item.Name == "Location") table.Location = Serialize.GetPointF(info.GetString("Location"));
                if (item.Name == "InternalRectangle") table.SetInternalRectangle(Serialize.GetRectangleF(info.GetString("InternalRectangle")));
                if (item.Name == "Rotation") table.Rotation = info.GetSingle("Rotation");
                if (item.Name == "Label") table.Label = (Label)info.GetValue("Label", typeof(Label));
                if (item.Name == "Image") table.Image = (Image)info.GetValue("Image", typeof(Image));
                //if (item.Name == "StencilItem") table.StencilItem = (StencilItem)info.GetValue("StencilItem", typeof(StencilItem));
                if (item.Name == "AllowMove") table.AllowMove = info.GetBoolean("AllowMove");
                if (item.Name == "AllowSnap") table.AllowSnap = info.GetBoolean("AllowSnap");
                if (item.Name == "AllowScale") table.AllowScale = info.GetBoolean("AllowScale");
                if (item.Name == "AllowRotate") table.AllowRotate = info.GetBoolean("AllowRotate");
                if (item.Name == "DrawSelected") table.DrawSelected = info.GetBoolean("DrawSelected");
                if (item.Name == "Selected") table.Selected = info.GetBoolean("Selected");
                if (item.Name == "KeepAspect") table.Selected = info.GetBoolean("KeepAspect");
                if (item.Name == "MinimumSize") table.MinimumSize = Serialize.GetSizeF(info.GetString("MinimumSize"));
                if (item.Name == "MaximumSize") table.MaximumSize = Serialize.GetSizeF(info.GetString("MaximumSize"));
                if (item.Name == "Direction") table.Direction = (Direction)Enum.Parse(typeof(Direction), info.GetString("Direction"), true);
                if (item.Name == "Interaction") table.Interaction = (UserInteraction)Enum.Parse(typeof(UserInteraction), info.GetString("Interaction"), true);
                if (item.Name == "Ports") table.Ports = (Ports)info.GetValue("Ports", typeof(Ports));
            return table;           

then add it to the default Surrogate 
  selector.AddSurrogate(typeof(Table), context, new TableSerializer());
I know I could do better but I needed something that could work quickly when I get time I will do more refactoring on it.
I hope this clears
May 23, 2016 at 1:18 PM
Hi everyone,

I try a lot of things but i cant save diagram.

Tab&Tabs SerializationException etc.
if (objectType.Name == "Tabs" || objectType.Name == "Tab")
            serializationSurrogate = SurrogateSelector.GetSurrogate(objectType.BaseType, Context, out selector1);              
            serializationSurrogate = SurrogateSelector.GetSurrogate(objectType, Context, out selector1);
i try like this, and i save but i dont open again succesfully.

Can i get .dll for successfull save? or