Asked by:
ScrollToHorizontalOffset used with Drag & Drop, mouse vs finger coordinates

Question
-
I have a GridView inside a ScrollViewer, and I want to be able to drag and drop items in the GridView to locations that are to the left or right of what is currently visible in the Viewport of the ScrollViewer. When the pointer is close to the left or right edge, I use a DispatcherTimer to repeatedly call ScrollToHorizontalOffset. The ScrollViewer scrolls the way I want it to, however, the left and right neighbours are not being computed correctly (for both the animation hinting and the actual drop) when I'm using my finger. The code I'm using in the ItemPanel to get the current position is e->GetPosition( this ), where e is the DragEventArgs being passed in to DragOver. Mouse and stylus give the correct left and right neighbours, but with my finger, it's as if the coordinates being passed into the ItemsPanel are the original, un-"ScrollToHorizontalOffset "-scrolled coordinates.
If I lift my finger and then move again (without causing ScrollToHorizontalOffset to be called), the correct left and right neighbours are found... until I scroll again.
At first I thought this was a laptop vs tablet problem, but when I plugged a mouse into my tablet, drag and drop worked correctly, just as with the laptop. I am testing with both a Samsung 700T Slate (x64) and a Windows ARM tablet.
Am I missing something somewhere to get the correct finger coordinates, or is there a bug somewhere in Microsoft code?
Andrea Mantler
Tuesday, February 26, 2013 12:45 AM
All replies
-
Can you please provide sample code and repro steps to demonstrate what you are talking about?
--Rob
Wednesday, February 27, 2013 2:05 AMModerator -
It's part of a large project... did you want just a few methods that contains the relevant code, etc, or should I make a small project that can replicate the behaviour? If you want a small project that you can compile and run, can you e-mail me one of those links I can use to send it to you? (Or do you have an alternate preferred method of getting it to you?) Thanks!
Andrea Mantler
Wednesday, February 27, 2013 5:11 PM -
I have a sample app that demonstrates the problem ready... let me know where I can send it, please. Thanks!
Andrea Mantler
Wednesday, February 27, 2013 6:28 PM -
Hi Andrea,
Can you please upload it to your Skydrive and post the link here?
Thanks,
RobWednesday, February 27, 2013 8:57 PMModerator -
That's interesting... how do you get the skydrive link from the app without sharing somewhere? I had to temporarily post the link to Facebook. >_< (I don't use the mail app, and so don't have it set up with an account.)
https://skydrive.live.com/redir?resid=61A6047A52D6275F%21201&authkey=%21AGi8KrO_9sPWKds
I didn't implement the full drag & drop behaviour, so things don't actually reorder in this app, but automatic scrolling is on (drag an item to the right or left edge of the screen, and 150 pixels from the edge it will start to scroll, moving faster the closer you are to the edge), and I've put in a debug print statement that will output the coordinates received to the output window.
With a mouse, you'll see that the x coordinate continues to increase as you drag an item to the right using autoscrolling. However, with your finger, you'll see that the x coordinate maxes out with whatever the right side of your screen is... that is, until you let go and restart dragging. (Also, you'll see the reorder hints are on the wrong items, due to the x coordinate being wrong.)
One more thing about the reorder hints: our items are arranged left-to-right across the "page" in rows, so hold the item being dragged between two items that are side-by-side to see the reorder hint.
Note: If you're testing on the Samsung slate, you'll have to keep moving your finger slightly, as it seems to have a time-out shut-off after about a second, and it acts like you've let go. (Do you happen to know any way to disable this?)
Also, if you happen to know of a better way to get the pointer coordinates for the auto-scrolling, I'd appreciate any tips you have.
Let me know if there's any other questions I can answer for you. Thanks Rob!
Andrea Mantler
- Edited by Andrea Mantler Wednesday, February 27, 2013 9:42 PM added detail about autoscroll
Wednesday, February 27, 2013 9:21 PM -
Hi Rob,
I see you're active on the forums, have you had a chance to look at the code yet? (I just wanted to make sure you didn't miss the "you've had a reply" e-mail, since you've responded to things that were started more recently than I posted the code.)
Thanks,
AndreaAndrea Mantler
Thursday, February 28, 2013 1:08 AM -
Hi Rob!
Were you able to observe the same bug I did? Have I stumped you too?
Cheers,
Andrea
Andrea Mantler
- Edited by Andrea Mantler Thursday, February 28, 2013 5:05 PM added question
Thursday, February 28, 2013 5:03 PM -
Hi Andrea,
I have downloaded your app, but I haven't had a chance to take a look at it yet. I hope to be able to do so this afternoon, but I cannot guarantee that.
You may also want to consider opening a support case at http://aka.ms/storesupport and somebody from my team will be able to help you one-on-one.
Best regards,
RobThursday, February 28, 2013 9:53 PMModerator -
Thanks! (Looking forward to when you do get a chance.)
Andrea Mantler
- Edited by Andrea Mantler Friday, March 1, 2013 12:18 AM added text
Thursday, February 28, 2013 10:38 PM -
Hi Rob,
I'm wondering if you've had a chance to look at the code yet?
Thanks,
AndreaAndrea Mantler
Monday, March 4, 2013 10:03 PM -
Hi Andrea,
I have not - I was off for the (long) weekend. I'll let you know once I have done so.
--Rob
Tuesday, March 5, 2013 12:47 AMModerator -
Hi Andrea,
I looked over your sample project and was able to reproduce the problem. The root of the difference is that touch and mouse scrolling are handled differently: touch input is handled by the Direct Manipulation engine in independent mode.
The problem appears to be that Direct Manipulation doesn't expect the ScrollViewer to move underneath it. It doesn't "physically" move the items while scrolling, it just translates them. I haven't tried this, but I suspect that you can compute the "true" position by adding the change in scrolling offset to the reported position.
--Rob
Tuesday, March 5, 2013 4:25 AMModerator -
Thanks Rob!
Please correct me if I'm wrong... I'm reading this as "there's a bug in the MS libraries, and I'm going to have to write a hack"? (I'm calling it a bug only because one MS team, the one dealing with mouse/stylus input, realized this was a possibility, but another team, the one dealing with finger input, didn't. I realize any "fixes" MS may do will happen long enough from now that I still need to implement my own hack, but are you able to pass along the information to the correct team so that there's a possibility of it being fixed in the future?)
It occurred to me last night that the auto-scrolling might already be implemented in the ScrollViewer and I just don't know about it, as I can see it being something that would get used a lot. Do you happen to know if there is an auto-scrolling feature that I just need to turn on?
I suspect you're right that I could update the layout panel with an offset, but this bothers me in terms of encapsulation, maintainability, and code-reuse (I may want to reuse this layout panel in another part of the app). From the DragEventArgs, is there even a way to tell if the pointer involved is a mouse/stylus (don't add the delta) or finger (add the delta)? Otherwise the hack to fix the finger drag would break the mouse/stylus drag.
I can think of two approaches that might have promise:
1. If the layout panel somehow gets the coordinates in screen coordinates, then traverses up the visual tree to determine what translations/scaling need to be done.
2. Seeing if I can use a Direct Manipulation (thanks for the link, I'm working at reading the related information now) event to pre-catch and modify the information that gets passed down to the DragOver handler and/or autoscrolling.
I don't know which of these are possible yet. Please let me know if you have any suggestions you think might be helpful.
Thanks!
AndreaAndrea Mantler
Tuesday, March 5, 2013 7:38 PM -
Update: I tried using the following method to transform the point, which gets the coordinates as a global position, then requests the transformation as a second step:
Point globalPosition = e->GetPosition( nullptr ); // position relative to screen
Windows::UI::Xaml::Media::GeneralTransform^ gt = TransformToVisual( nullptr )->Inverse;
Point transformedPosition = gt->TransformPoint( globalPosition );This has the same mouse vs finger problem. I'm now pretty convinced that the problem isn't the actual coordinates coming in, but a transformation matrix that isn't being updated when it needs to be, probably at the ScrollViewer level. So, the question isn't "how to fix the coordinates", but "how to update the transform correctly". (If anyone has any suggestions...?)
Andrea Mantler
- Edited by Andrea Mantler Tuesday, March 12, 2013 11:12 PM
Tuesday, March 12, 2013 11:12 PM -
Solution found in this thread: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/f21fa2ad-2065-4d50-9fc6-217060df9e2c
Setting my GridView's ManipulationMode to None fixed the problem!Andrea Mantler
- Marked as answer by Andrea Mantler Wednesday, March 13, 2013 8:46 PM
- Unmarked as answer by Andrea Mantler Wednesday, March 13, 2013 8:59 PM
Wednesday, March 13, 2013 8:46 PM -
Crud, spoke too soon. Now regular scrolling doesn't work. >_<
Andrea Mantler
Wednesday, March 13, 2013 8:59 PM