The steps include:
- Create some control to hold the graphics, derive your class from
System.Windows.Forms.Control
or System.Windows.Forms.Control
. You can even use your Form
, but to my taste, it won't be flexible enough. - In your graphic control, use
SetStyle
and add the styles System.Windows.Forms.AllPaintingInWmPaint | System.Windows.Forms.OptimizedDoubleBuffer
. It will help you to avoid flicker. This is one reason of using subclassing of the control class, as System.Windows.Forms.Control.SetStyle
is protected.
See http://msdn.microsoft.com/en-us/library/system.windows.forms.control.aspx[^]. - Create a data model of the graph. In the design of data structure, try to isolate 1) pure logical graph data: a graph is a relationship on the set of
graph vertices
, include just noted and relationship information, 2) graphical data — position of notes, form of arches, etc., 3) view options, such as zoom, shift, color, etc. - Make model persist using Data Contract, see:
http://msdn.microsoft.com/en-us/library/ms733127.aspx[^],
How can I utilize XML File streamwriter and reader in my form application?[^],
Creating property files...[^],
deseralize a json string array[^].
With the data contract serializers (see the references above) you can use persist data as XML or JSON. - Create a method of rendering of the instance of the data model using an instance of the class
System.Drawing.Graphics
using methods of this class, and instance of which should be a parameter of this method. It is very important to parametrize the instance of the Graphics
, because it could be not only the one of your graphics control, but anything else, for example, the one of the printer, bitmap, etc. - Override the method
OnPaint
of your graphics control. It should simply call the method developed on the previous step. - Develop methods of modification of the data model of graph: adding and removing vertices and arches, re-routing arches, etc. Add methods of changing graphics detail, view options, all according three parts or aspects of the data model described above. Remember: you should never modify graphics itself (see next item), you only need to modify the model.
- Develop the method of invalidation of the graphics which should trigger re-painting of all the scene or part of it. In all cases, this ultimately calls one of the methods
System.Windows.Forms.Control.Invalidate
. A method without parameters invalidates whole control, methods with parameters (Rectangle
or Region
) allows to invalidate and hence redraw only a part of graphics, in order to improve performance (make sure you really need it, as it depends on the volume of you graphics; do some performance tests). - Develop methods of changing the model in response to keyboard/mouse events. It should include selection, dragging, context menu with operations (remove, move, rename of selected element, etc.). After each such modification, call appropriate invalidation method described in the previous item.
- PROFIT!
Additional recipe is this: think about switching to WPF using
Canvas
. In this approach, there is no rendering problem. A big deal of methods described above is already implemented and transparent to the developer. All graphics is vector. Consider zoom and panning already implemented for you. You can even use already implemented animation.
This plan is good enough to work with arbitrary graphs, not only trees. The nature of the graph does not really matter: many data structure can be represented as a tree, and almost all thinkable finite structures — as a graph.
This is quite a plan. You will need to design all the parts, tests them, put all together and implement all the application. Get to work!
—SA