Move nodes with arrow keys

Hello Walter,

I need the user to be able to move currently selected nodes via keyboard arrow keys but I don’t know how. None of the similar questions target GoXam with WPF and I couldn’t adapt the code in the answers. I tried attaching a KeyDown command handler to the Diagram, to the Nodes and I’ve overridden the DoKeyDown in the CommandHandler but nothing even gets called.

So, how can I get the keyboard’s arrow keys to move the nodes?

You could add a PreviewKeyDown event handler on the Diagram to do something like:

    if (e.Key == Key.Down || e.Key == Key.Up || e.Key == Key.Right || e.Key == Key.Left) {
        e.handled = true;
        myDiagram.StartTransaction("move selection");
        foreach (Part part in myDiagram.SelectedParts) {
          Node n = part as Node;
          Point pos = n.Position;
          switch (e.Key) {
            case Key.Down: n.Move(new Point(pos.X, pos.Y+10), false); break;
            case Key.Up: n.Move(new Point(pos.X, pos.Y-10), false); break;
            case Key.Right: n.Move(new Point(pos.X+10, pos.Y), false); break;
            case Key.Left: n.Move(new Point(pos.X-10, pos.Y), false); break;
          }
        }
        myDiagram.CommitTransaction("move selection");
    }

Like this?

private void InitializeDiagramData(...) {
    ...
    this.Diagram.KeyDown += OnKeyDown;
}

private void OnKeyDown(object sender, KeyEventArgs eventArgs) {
    ...
}

As I’ve said, I tried that already but the event handler never gets hit.

I’ve just realized it does get hit when I press some character keys, an F1-12 button or the ctrl key, perhaps others as well. But it does not get hit when pressing an arrow key. As the diagram scrolls upon pressing the arrow keys is it possible there’s a default KeyDown handler suppressing my added one, which I have to remove first?

Sorry, I wasn’t clear – you probably want to use the PreviewKeyDown event instead.

That does work, thanks. The diagram still scrolls, though. How do I prevent it from?

Did you set e.handled = true?

Ah, I missed that line. Thanks.

There is another problem: I have a custom DraggingTool with an overridden MoveParts method, which calculates the length of a link and displays the result in a textbox of that link.

However, the MoveParts method does not get called upon moving the nodes using Node.Move(...). Is there a way to move the nodes via the dragging tool or do I have to recalculate the links’ length in the key down event handler?

I would think that you would want to update that textbox on the link whenever the link’s route is recalculated.

You might be able to do that in a binding of Link.Route.Points – I haven’t tried that.

But you can certainly override Route.ComputePoints. Call the base method and if it returns true, modify the TextBlock label with whatever string you like.

So, I create a class derived from Route. When do I best pass that derived class to the link?

In the XAML for your Link template, set Link.Route to an instance of your custom Route.