Initial, Automatic, and Programmatic Viewport Management

Once you have created and assigned a model to cause some Parts to appear in your Diagram, you can control where your parts initially appear in the viewport, and you can control where they are shown after the diagram has been modified.

Initial viewport

You can very easily set the Diagram.InitialPosition and/or Diagram.InitialScale properties at any time, even before assigning the model. This will cause the Diagram.Position and/or Diagram.Scale properties to be set to the specified initial value(s) once all of the Parts have been created and any initial layout has been performed.

But what if you do not know how big your diagram document will be? If you want to show a particular area of the document, you will not know what position to set. If you want to show a big document at the largest scale that shows all of it, you will not know what scale to set.

One solution to this problem is to set the Diagram.InitialDocumentSpot and Diagram.InitialViewportSpot properties to particular Spot values. For example, if you are showing a tree-like diagram and you want tree to be centered horizontally but positioned vertically at the top, you can do something like this when you create the Diagram:


  diagram.InitialDocumentSpot = Spot.Top;
  diagram.InitialViewportSpot = Spot.Top;

This makes sure that after the initial layout of your diagram the middle top point of the diagram contents is positioned to be at the middle top point of the viewport.

Another solution to this problem is to set the Diagram.InitialContentAlignment or Diagram.InitialAutoScale properties. For example it is fairly common to want to make sure that small documents appear top-centered within the diagram window -- just set Diagram.InitialContentAlignment to Spot.Top. Or if you want to "zoom-to-fit" the diagram, just set Diagram.InitialAutoScale to AutoScale.Uniform.


  diagram.InitialAutoScale = AutoScale.Uniform;

More generally, you may want to try to center a particular Node. Here is how you can do that:


  diagram.NodeTemplate =
    new Node("Auto") { LocationSpot = Spot.Center }
      .Bind("Location")
      .Add(
        new Shape { Fill = "lightyellow" },
        new TextBlock() { Margin = 5 }
          .Bind("Text", "Location", l => ((Point)l).X.ToString("N2") + ", " + ((Point)l).Y.ToString("N2"))
      );

  // initialize the model with random nodes:
  var rand = new Random();
  var nodeDataList = new List<NodeData>();
  for (var i = 0; i < 20; i++) {
    nodeDataList.Add(new NodeData { Location = new Point(rand.NextDouble() * 600, rand.NextDouble() * 300) });
  }
  diagram.Model = new MyModel {
    NodeDataSource = nodeDataList
  };

  // this event handler is called when the diagram is first ready
  diagram.InitialLayoutCompleted += (s, e) => {
    var d = e.Diagram;
    var model = d.Model;
    // pick a random node data
    var data = model.NodeDataSource.ElementAt((int)Math.Floor(new Random().NextDouble() * model.NodeDataSource.Count()));
    // find the corresponding Node
    var node = d.FindNodeForData(data);
    // and center it and select it
    d.CenterRect(node.ActualBounds);
    d.Select(node);
  };

Note: because by default one cannot scroll past any edge of the document plus any Diagram.ScrollMargin, if the selected node happens to be at or near an edge, the node cannot actually be centered in the viewport.

Automatic viewport management

There are also times when you will want to control the viewport (i.e. the Diagram.Position and Diagram.Scale) after every change to the diagram. For example, if you always want to keep the document centered after the user has moved or deleted or inserted nodes, set Diagram.ContentAlignment (rather than Diagram.InitialContentAlignment) to Spot.Center.

Or if you always want to keep the document "zoomed-to-fit", set Diagram.AutoScale (rather than Diagram.InitialAutoScale) to AutoScale.Uniform. As an example, the Overview diagram does this.

Programmatic viewport management

If you do not want continual repositioning or rescaling of the diagram, but you do sometimes want to change the Diagram.Position and/or the Diagram.Scale, you can set those properties to whatever values you like. However, please note that the ultimate value for Diagram.Position is normally limited by the Diagram.DocumentBounds and the size of the viewport and the scale of the diagram. The Diagram.Scale is limited by Diagram.MinScale and Diagram.MaxScale.

But it is more common to call a method on Diagram to achieve the results that you want. For example, to get the effect of the Diagram.InitialDocumentSpot and Diagram.InitialViewportSpot properties that are used when the "InitialLayoutCompleted" DiagramEvent occurs, call Diagram.AlignDocument with the two desired Spots that you want to have coincide.

As already demonstrated above, if you want to try to center a particular node in the viewport, you can call Diagram.CenterRect with the node's GraphObject.ActualBounds.

If you want to make sure that a particular node is within the viewport, but not necessarily centered, call Diagram.ScrollToRect.

If you just want to scroll the diagram, in the same manners as the user might via a scrollbar or the mouse wheel, call Diagram.Scroll with arguments that specify how much to scroll and in which direction.

The just-mentioned Diagram methods do not change the Diagram.Scale. If you want to rescale the diagram so that the whole document bounds are shown, call Diagram.ZoomToFit. More generally, if you want a particular area of your diagram to be shown at whatever scale will make it fit in the viewport, call Diagram.ZoomToRect.