Problem with drag and drop external data

My data model contains an observable collection. I have two views for this observable collection, one of them is a graph view using GoXAM. I have been using the FlowGrammer sample as the basis for my graph view. Each item in the data model collection is represented by a node in the graph. The links in the graph represent the order of the data in the collection. I have a palette of objects that I want to be able to add to the observable collection in the data model. I want to be able to add the objects from the palette by double clicking on them. This just adds the item to the end of the data list. I also want to insert items into the data list by drag and drop on an existing link or node in the graph which will insert the object into the data model collection in the appropriate place. The drag data when dragging from the palette is not the same data type as my graph nodes. This palette is used by both views so the drag data when dragging from the palette cannot be the same data type as the graph nodes. Once a node is created in the graph I want to be able to move its position in the data model list by drag and drop.

I created a graph view model that monitors the data model collection for changes and then calls a method in the graph model where the appropriate nodes and links are added. I also implemented a custom dragging tool which overrides the DropOnto method. This DropOnto method does not change any of the nodes or links in the graph, it only makes changes to the data model collection. This works great. When I double click on an object in the palette, an item gets added to the end of the data model collection list, the view model gets notified of the change and calls appropriate method in the graph model to change the nodes and links as needed. And it all shows up in the graph. If I move items in the other view, the view model gets notified, makes appropriate changes to nodes and links and it all shows up correct. If I move an item in the graph view, everything in both views looks correct.

The problem is when I override the OnDrop method in the custom dragging tool. I drop an object from the palette and add or insert an item into the data model collection. The graph view model gets notified of the change, calls the appropriate method in the graph model to change the nodes and links as needed. The new node and links do not show up in the graph. The changes to the nodes and links all look correct when I check the graph model NodesSource and LinksSource. They just do not appear in the graph.

Do you have any idea why the nodes do not show up? Thanks!

Did you really mean the DraggingTool.OnDrop method? That isn’t called. You should ignore all UIElement and FrameworkElement properties and methods of all tools (and of CommandHandler and all layouts) and other objects that are not in the visual tree. What is normally called is DraggingTool.DoDrop.

Drag-and-drop events actually happen on DiagramPanel, which overrides OnDrop, and which normalize and save the event information and then call DraggingTool.DoDrop.

So that explains why nothing seems to be happening.

I’m not sure what would be best for your app. You should look into overriding DraggingTool.MayAcceptData and AcceptData. Then in your override of DoDrop, if you don’t like the default behavior of adding the data to the model, you can immediately remove it and call your own model’s methods for adding what you really want that will be reflected in the diagram model.

Sorry, yes, the method that I overrode was DraggingTool.DoDrop not OnDrop.

I would not say that nothing seems to be happening. My DraggingTool.DoDrop method does get called as expected. In it, I change the data model’s collection. After the collection list is changed my view model gets notified and adds the nodes and links to the model. As I said before, the graph model’s NodesSource and LinksSource lists look correct. Just the new nodes and links do not appear in the graph.

The new nodes do not seem to ever get a location assigned though, it is always NaN. I am guessing that the links do not show up because they are connected to a node that is not visible. Maybe the node is not visible because it is never given a valid location. But why is the layout manager not setting its location? I have StartTransaction - CommitTransaction around all calls to add or remove nodes and links. In fact it is the same code that is used when adding objects by double clicking in the palette and it works fine then. I am using a LayeredDigraphLayout, but I have tried just using the standard layout and the same thing seems to happen.

I do not see where the DraggingTool has MayAcceptData or AcceptData methods. I did override DraggingTool.MayCopyExternal in order to get this to work as far as it has.

A Node with NaN,NaN location will not be visible. You are right that any layout ought to be setting the Location of all of the Nodes that it is laying out.

Is there anything that you as a user can do to the diagram afterwards to get the new node(s) and link(s) to appear? I’m wondering if the calls to StartTransaction and CommitTransaction are not matched up, so it’s never actually finishing the outermost transaction. You could look at the UndoManager.TransactionLevel.

The [May]AcceptData methods on DraggingTool are new for version 1.3.

No, there is nothing the user can do to make the new nodes appear. In fact once it is broken, no new nodes will appear even if added by double clicking on the item in the palette rather than dragging from it.

I was already checking DiagramModel.IsInTransaction before starting a new transaction and it always came back false. I was not using an UndoManager but added one to check the transaction level before starting a new transaction and it is always 0.

I did notice something interesting though. Just dragging an object from the palette over the graph causes the problem even if you do not drop it on the graph or change anything in the models. So, maybe it has something to do with the DraggingTool.DragOver method. I pretty much copied this from your FlowGrammer sample. It doesn’t cause any problem when moving existing nodes. It does cause a problem when dragging external data. Do you have any idea why this would be a problem?

I can’t think of anything at the moment. I suppose you could try excising code from your custom DraggingTool to see what might be the cause. Try it first without providing feedback during the drag-over.

After a drag-over, is the user still able to move or delete the old nodes in the diagram?

I removed all the code from DraggingTool.DragOver and it still causes the same problem. It seems the problem only happens when MayCopyExternal returns true. What happens when MayCopyExternal returns true? Does that give you any clue what might be causing this problem?

Yes, after the problem starts the user can move and delete old nodes in the diagram. However, the layout changes. It no longer shows all the nodes in one horizontal row. Sometimes it puts each node in its own row. Sometimes it splits them into two rows with an offset.

If you want to allow nodes (data) to be copied from the palette to the target diagram, MayCopyExternal has to return true. That’s the normal behavior when dragging from another control when the data format matches, assuming no shift key.

I really have no idea of what might be happening in your app. I don’t recall ever hearing about anything like that (given that there’s no problem with transactions).