Move Node gives a lot of Edits in ModelChanged

Hi Walter,

We are making use of Model Changed event and we are relying on ModelChanged Edits. But the problem is that we are getting multiple edits for a single move node which is affecting our further logic.

Is there any way that we can get the last edit or the final location of the node ?

Please follow the image below:
MicrosoftTeams-image (5)

Try setting DraggingTool.isRealtime to false:
http://goxam.com/3.0/apiCore/index.html#Northwoods.GoWPF~Northwoods.GoXam.Tool.DraggingTool~IsRealtime.html

Thanks Walter !! That helped

Hi Walter,

We are facing another issue because of the above code changes.

What we have for copy-paste is once the user selects and Copies the nodes and connections and pastes. The pasted elements will be sticking to the mouse pointer and it will be so until the user clicks some where on the diagram. And once he clicks the elements will be put at that location.
This is the reference image:

But after setting the above property this feature behaves awkwardly. See image below

MicrosoftTeams-image (6)
Any suggestions ?

It sounds as if there were an exception that happened at some time. Can you confirm that and find the cause?

Have you overridden any tool or commandhandler methods? I’d like to reproduce the problem.

We have the similar implementation for Dragging tool as here Copy with Mouse and also have some overriden methods in commandHandler. Didn’t get any exception thrown from GoXam control though.

I just tried this in a moderately complicated app:

      <go:Diagram.DraggingTool>
        <go:DraggingTool IsRealtime="False" />
      </go:Diagram.DraggingTool>

and I was unable to encounter any problems with copy-and-paste and dragging.

So there must be some complication in your customizations of dragging (or copy-pasting) that are causing the problem.

I still think there is an unexpected exception happening, but it’s not likely to be uncaught. It might be muffled by the diagram. You’ll have to notice uncaught exceptions in the debugger.

After understanding the goXam code base I found that the purple lines are added by a method in DraggingTool named “MakeDragImage”. This method is called when “IsRealtime” is set to false.

I tried overriding this method but the problem is if I am adding the nodes after overriding this method, the edits are increasing. It didn’t help me.

Is there any way that I can filter from the diagram edits to get first and the last edit for move of node or link?

I guess I do not understand what the awkwardness is that you first described in this topic. What is it that you really want?

In the two images above the first one refers to the functionality before setting the IsRealTime to false and the second one is after setting the IsRealTime to false.

I expect after setting IsRealTime property to false it should behave in the same was as in image. Rather I see the purple borders. That is the problem.

MakeDragImage must not have side-effects. It is only responsible for producing the image to be dragged instead of the actual Parts.

Try this code, which I haven’t tried in years:

    protected override FrameworkElement MakeDragImage(Rect bounds) {
      var viewportBounds = this.Diagram.Panel.ViewportBounds;
      var imgLayer = new NodeLayer();
      var origLayers = new Dictionary<NodeLayer, Node>();
      foreach (var part in this.DraggedParts.Keys) {
        Node node = part as Node;
        if (node != null) {
          var origlayer = (NodeLayer)node.Layer;
          origLayers[origlayer] = node;
          origlayer.InternalRemove(node);
          imgLayer.InternalAdd(node);
        }
      }
      imgLayer.Measure(new Size(bounds.Width, bounds.Height));
      imgLayer.Arrange(new Rect(0, 0, bounds.Width, bounds.Height));
      try {
        var bmp = new RenderTargetBitmap((int)Math.Ceiling(bounds.Width (int)Math.Ceiling(bounds.Height), 96, 96, PixelFormats.Pbgra32);
        imgLayer.Opacity = 0.75;
        imgLayer.RenderTransform = new TranslateTransform(-bounds.X, -bounds.Y);
        bmp.Render(imgLayer);
        bmp.Freeze();
        rect.Fill = new ImageBrush() {
          ImageSource = bmp,
          Stretch = Stretch.None,
        };
      } finally {
          foreach (var pvk in origLayers) {
            var node = (Node)pvk.Value;
            imgLayer.InternalRemove(node);
            var layer = pvk.Key as NodeLayer;
            if (layer != null) layer.InternalAdd(node);
          }
      }
      return rect;
    }

Tried this solution but this expects some of the internal goXam methods to be made as public.

We tried another way, That is in ModelChanged event which we are subscribing, before starting with the logic, we find all those edits which are related to Property = “Location” and remove all edits except the last and thus we maintain the older behavior of moving objects after paste and also have limited the number of edits for edits( for Property=“Location”). With this implementation we are able to achieve what we wanted.

What are your thoughts about this ? Will this have any side effects ?

Yes, that should work, but you have to keep the first and the last ModelChanged event for each Part. The first is need for undo to work correctly; the last for redo.

Oh yeah. I had missed the undo-redo part. Thanks for letting me know. I will handle it accordingly.