Pages

Wednesday, October 22, 2014

The Simplest WPF Diagram Designer - Part 3

2 weeks ago I started a series of tips about WPF Diagram Designer (part1, part2). But as you know, there is nothing new under the sun. I have been pointed that there were few similar articles already posted on CodeProject so I`ve decided to post my next part of work here. I will add basic keyboard binding and RavenDB/XML save-load functionality. The source code can be found here: https://bitbucket.org/JleruOHeP/mywpfdesigner/src.

Keyboard commands
I have added 2 commands: Delete the current element and edit the text of the current element.
For the sake of simplicity I have changed the meaning of the Tag property for shapes. Now it stores the shape entity itself instead of just the Id. Because of that it became much faster to work with them. Because user can`t select the line we need to delete the connector, line and the opposite connector when someone selects the connector and presses Del. Now the Connector should know not only its host but as well its line. Ok. And the ChangeText command is really simple - as we already have all needed functionality.

RavenDB
I wanted to pick some embedded NoSQL database and the RavenDB was an obvious choice. I added wrapper class for that matter with a static EmbeddableDocumentStore DocumentStore and 2 methods - to Save the whole model or to load all objects of a specific type. With that implementation there is nothing complex about saving and for loading you have to clear the Canvas, reinitialize lines (because they do not store their coordinates - only connectors; connectors should be reconnected to their hosts), redraw the shapes, and finally recreate the Model class (assign proper commands and set it as a DataContext for a Window).

Also as the connectors are not used as a separate entity - I removed them from the model class. Now there are only 2 collections - for lines and shapes.

XML Serialization
It is really simple. Our Model class already has everything it needs - so we can easily use the XmlSerializer class.

 var serializer = new XmlSerializer(typeof(MyCanvasModel));
 using (var writer = new StreamWriter("data.xml"))
 {
  serializer.Serialize(writer, Model);
  writer.Close();
 }

The only thing we need to add - is [XmlIgnore] attribute for all the commands because they cant be serialized.