Building Parts with GraphObjects

You can construct a Node or other kind of Part in traditional C# code. GoDiagram also offers a more declarative-looking manner of building parts that has several advantages over code.

The following pages will discuss the basic kinds of objects you can use to build a node. These pages build up a diagram by explicitly creating and adding nodes and links. Later pages will show how to build diagrams using models rather than using such code.

First, look at a diagram that includes comments about the GraphObjects used to build some example nodes and links:

As you can see, a node or a link can be composed of many GraphObjects, including Panels that may be nested.

Building with Code

A GraphObject is an object that can be constructed and initialized in the same manner as any other object. A Node is a GraphObject that contains GraphObjects such as TextBlocks, Shapes, Pictures, and Panels that may contain yet more GraphObjects.

A very simple Node might consist of a Shape and a TextBlock. You can build such a visual tree of GraphObjects using code such as:


  var node = new Node();
  node.Type = PanelLayoutAuto.Instance;
  var shape = new Shape();
  shape.Figure = "RoundedRectangle";
  shape.Fill = "lightblue";
  node.Add(shape);
  var textblock = new TextBlock();
  textblock.Text = "Hello!";
  textblock.Margin = 5;
  node.Add(textblock);
  myDiagram.Add(node);

This code produces the following diagram.

Although building a node in this manner will work, as the nodes get more complicated the code will become more complicated to read and to maintain. Fortunately GoDiagram has a better way to make Parts out of GraphObjects.

Furthermore, later sections will discuss how Nodes and Links should be created automatically using models, templates, and data-binding. Until that time, these pages will create Nodes explicitly and add them to Diagrams directly.

Building Fluently

GoDiagram includes parameterized constructors and fluent methods that are very useful in constructing GraphObjects without having to think of and keep track of temporary variable names. These methods also support building elements in a nested fashion, where the indentation gives you a clue about depth in the visual tree, unlike the simple linear code shown above.

We can rewrite the code above fluently using to produce exactly the same results:


  myDiagram.Add(
    new Node { Type = PanelLayoutAuto.Instance }
      .Add(
        new Shape { Figure = "RoundedRectangle", Fill = "lightblue" },
        new TextBlock { Text = "Hello!", Margin = 5 }
      )
  );

This can be simplified a bit by using string arguments:


  myDiagram.Add(
    new Node("Auto")  // or PanelType.Auto
      .Add(
        new Shape("RoundedRectangle") { Fill = "lightblue" },
        new TextBlock("Hello!") { Margin = 5 }
      )
  );

Notice how we set the Panel.Type, Shape.Figure, and TextBlock.Text properties by just passing the string value to the constructors.

All of this initialization using fluent methods is still C# code, so we can call functions and easily share objects such as brushes:


  var violetbrush = new Brush(new LinearGradientPaint(new (float, string)[] {
    (0, "violet"), (1, "lavender") }
  ));

  myDiagram.Add(
    new Node("Auto")
      .Add(
        new Shape("RoundedRectangle") { Fill = violetbrush },
        new TextBlock("Hello!") { Margin = 5 }
      )
  );

  myDiagram.Add(
    new Node("Auto")
      .Add(
        new Shape("RoundedRectangle") { Fill = violetbrush },
        new TextBlock("Goodbye!") { Margin = 5 }
      )
  );

Brushes and Geometry objects may be shared, but GraphObjects may not be shared.

The following pages will provide more details about the basic building block classes, TextBlock, Shape, and Picture, and about ways of aggregating them with the Panel class.