Hi everyone - just wondering if it was possible to draw your own ‘link’ route between ports instead of using one of the ‘Routing’ types (Ortogonal for example). I was thinking I could just set all the points manually after the link is added to the diagram, but it doesnt seem to work.
My guess is that you are setting the points too soon in the initialization/loading of your diagram.
I suggest you try moving your Route points-setting code to a Diagram.LayoutCompleted event handler, or perhaps to a Diagram.InitialLayoutCompleted event handler.
Here’s an example of what I’m talking about, taken from an updated version of the StateChart sample:
First, we’ll add a Points property to the Transition link data class:
[code] public List Points {
get { return _Points; }
set {
List old = _Points;
List val = value ?? new List();
if (old != val && !old.SequenceEqual(val)) {
_Points = val;
RaisePropertyChanged(“Points”, old, val);
}
}
}
private List _Points = new List();
// read and write the extra property on the link data
public override XElement MakeXElement(XName n) {
XElement e = base.MakeXElement(n);
e.Add(XHelper.Attribute("Curviness", this.Curviness, Double.NaN));
e.Add(XHelper.Attribute("Points", this.Points, new List<Point>()));
return e;
}
public override void LoadFromXElement(XElement e) {
base.LoadFromXElement(e);
this.Curviness = XHelper.Read("Curviness", e, Double.NaN);
this.Points = new List<Point>(XHelper.Read("Points", e, new List<Point>()));
}[/code]
Then we can augment the behavior of “Save” and “Load”:
[code] private void Save_Click(object sender, RoutedEventArgs e) {
var model = myDiagram.Model as GraphLinksModel<State, String, String, Transition>;
if (model == null) return;
// copy the Route.Points into each Transition data
foreach (Link link in myDiagram.Links) {
Transition transition = (Transition)link.Data;
if (transition == null) continue;
transition.Points = new List(link.Route.Points);
}
XElement root = model.Save<State, Transition>(“StateChart”, “State”, “Transition”);
Demo.MainPage.Instance.SavedXML = root.ToString();
LoadButton.IsEnabled = true;
model.IsModified = false;
}
private void Load_Click(object sender, RoutedEventArgs e) {
var model = myDiagram.Model as GraphLinksModel<State, String, String, Transition>;
if (model == null) return;
try {
XElement root = XElement.Parse(Demo.MainPage.Instance.SavedXML);
// set the Route.Points after nodes have been built and the layout has finished
myDiagram.LayoutCompleted += UpdateRoutes;
model.Load<State, Transition>(root, "State", "Transition");
} catch (Exception ex) {
MessageBox.Show(ex.ToString());
}
model.IsModified = false;
}
// only use the saved route points until after the layout has completed,
// because links will get the default routing
private void UpdateRoutes(object sender, DiagramEventArgs e) {
// just set the Route points once per Load
myDiagram.LayoutCompleted -= UpdateRoutes;
foreach (Link link in myDiagram.Links) {
Transition transition = link.Data as Transition;
if (transition != null && transition.Points.Count > 1) {
link.Route.Points = transition.Points;
}
}
}[/code]
Awsome, that was it! It works great now!
By the way, for version 1.2 we’re adding a Points property to GraphLinksModelLinkData, so you won’t need to add that code to the Transition class representing link data.