WPF DragDrop sample and Viewbox - beware...

In a post a few months ago, I included a sample that showed how to use an adorner to display a 'preview' during a drag/drop operation.


And yet... dire news came in - someone was having a problem with this. Someone played around with the display, and the adorner wasn't following the mouse like it should. Peter Sarrett was kind enough to look into this - here is his response. My immense thanks for his help.

Here's what's happening.

The grid is inside a Viewbox, which uses a scaling transform to alter the size of the grid. Your code is asking for the position of the mouse relative to the grid, which is inside that transform. So the point you get back is scaled.

The adorner picks up the scale from the Viewbox, and then you add a translation transform using already-scaled values. This makes the translation out of sync.

Perhaps an example will be clearer.

The window is resized to be 1/5 as big. The grid gets a 20% scale. You drag the mouse 5 pixels away from the edge of the grid. This gets scaled so that, to the grid, you've moved 25 pixels, and so the position that gets reported back is 25. You set the adorner's offset to be 25. The adorner picks up the scale on the grid, and scales the adorner down to be 20% of normal. Then it sets its offset to be 25 pixels, which is now way out of scale. Since the adorner is already scaled, this value is too large and results in a huge movement of the adorner.

Fortunately, the solution is simple. In GetDesiredTransform, you need to add the translation transform to result.Children BEFORE you add base.GetDesiredTransform(transform) , instead of after as you currently do. This will allow the translation to be scaled along with the rest of the adorner. I tried this locally and it produces the desired results.

And that should fix it. Voilá! I'll go and update the old article to include this, just in case.