WPF 4 multi-touch drag and drop - wpf

I have a WPF 4 application where I have implemented Drag and Drop using the standard DragDrop.DoDragDrop approach, but Im doing it using touch instead of Mouse events.
My XAML for my Grid (that Im dragging) is as follows:
<Grid x:Name="LayoutRoot"
ManipulationStarting="ManipulationStarting"
ManipulationDelta="ManipulationDelta"
ManipulationCompleted="ManipulationCompleted"
IsManipulationEnabled="True">
<!-- children in here -->
</Grid>
Now the code behind is like this:
private void ManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
e.ManipulationContainer = this;
e.Handled = true;
}
private void ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
e.Handled = true;
DragDrop.DoDragDrop(this, new DataObject(GetType(), this), DragDropEffects.Move);
}
private void ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
//completed stuff
}
BUT when I try to drag with one finger while already dragging with another finger (different hands for example, which would simulate two people) the second touches don't seem to register properly, infact, it seems that windows thinks that my two fingers are trying to scale (like a pinch gesture)...
Does anyone know a way to get around this?
Thanks a lot
Mark

For multi-touch, you're going to want to use the Surface Toolkit for Windows Touch. It includes a drag-and-drop framework suitable for multi-touch scenarios. It includes a drag-and-drop framework. That link includes several how-to scenarios.

Although this is just an educated guess, I would say that DragDrop.DoDragDrop() is not capable to handle multiple drag guestures in parallel.
Indices:
There's no possibility to pass a touch ID to the method (which would be neccessary for differentiating the ongoing drag gestures)
The implementation of DoDragDrop() is static
The call of DoDragDrop() is blocking until the drop occured or was canceled
It is based upon the OLE version of drag and drop (which was not updated for Win7)
However, I would be glad if someone could correct me in this matter, because I'm currently also searching an DND API suitable for touch support.
Regards,
Seven

Related

How to determine if button was clicked or touched?

Is there a way to distinguish whether a button was clicked as in with a mouse or touched using a touchscreen in WPF?
You can subscribe to PreviewMouseDown and PreviewTouchDown.
Page.xaml
<Button PreviewMouseDown="Button_PreviewMouseDown"
PreviewTouchDown="Button_PreviewTouchDown" />
Page.xaml.cs
private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Mouse was used.");
}
private void Button_PreviewTouchDown(object sender, TouchEventArgs e)
{
MessageBox.Show("Touchscreen was used.");
}
I don't believe you'll be able to access the eventargs of either in the actual click event.
If you need to perform work there as opposed to the preview events I would recommend setting an instance variable in the preview events so when you get to the click event you know where you came from.
You have to set up an event handler. In the designer, double click on the button and that will set on up for you.
Then in the code behind add what ever code you want.
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Title = "Clicked";
}
You can add Touch events as well TouchDown, TouchUp, etc.
Windows 7 and its higher versions have the ability to receive input from multiple touch-sensitive devices. WPF applications can also handle touch input as other input, such as the mouse or keyboard, by raising events when a touch occurs.
WPF exposes two types of events when a touch occurs − touch events and manipulation events. Touch events provide raw data about each finger on a touchscreen and its movement. Manipulation events interpret the input as certain actions. Both types of events are discussed in this section.
WPF enables applications to respond to touch. For example, you can interact with an application by using one or more fingers on a touch-sensitive device, such as a touchscreen This walkthrough creates an application that enables the user to move, resize, or rotate a single object by using touch.
Source MSDN : https://msdn.microsoft.com/en-us/library/ee649090.aspx
Also read this codeproject article - http://www.codeproject.com/Articles/692286/WPF-and-multi-touch

Simple One Finger Touch Event

Does anyone know how I can implement a single Touch Event. A simple, one finger touch event, not multiple gesture or anything... Just a simple one finger touch.
I want to learn how to do this instead of doing LeftButtonMouseUp.
Add this to any control:
XAML
Tap="Control_Tap"
CodeBehind
private void Control_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
// Tap Logic
}
Here is a link to the Gesture cheat sheet

C#: Drag and Drop in WPF (Richtextbox)

i want to implement a Drag/Drop mechanic in WPF, but it didn't work...
With Windows-Forms it worked, ...
First i set AllowDrop to True. In windows-forms you can already drag items into the richtextbox and the cursor changes.
With WPF .... nothing happens.
The nexT point: Implement DragEnter and DragDrop Methodes.
I did it like the online-manuals says. (ok i had to try out something more, because DragDrop doesn't exists in WPF)
I think all tutorials for drag/drop is only for Windowsforms, nothing for WPF...
Is there a problem with the richtextbox? If i change it to "allowDrop" - nothing happens. The cursor is still a not-allowed-symbol.
Hope someone can help :)
Examplecode from tutorials i read:
richTextBox1.AllowDrop = true;
void richTextBox1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.None;
if (e.Data.GetDataPresent(DataFormats.XXX))
{
e.Effect = DragDropEffects.Copy;
}
}
void richTextBox1_DragDrop(object sender, DragEventArgs e)
{
//intert in richtextbox ...
richTextBox1.methodeXY();
}
I was curious as to why so I had a little play and eventually got it to work. Essentially, I started by binding to the PreviewXXX events like so:
AllowDrop="True" PreviewDragEnter="RichTextBox_DragEnter" PreviewDragOver="RichTextBox_DragEnter" PreviewDrop="RichTextBox_Drop"
Even still, they STILL didn't work. But the answer came here, in the form of elevated permissions. I usually run VS2010 with admin elevation. Because I was dropping some files from Explorer onto my RichTextBox, it was essentially banning the operation because Explorer runs in a non-elevated user mode. Running the VS2010 in a non-elevated mode fixed the problem. The article linked does suggest some workarounds, but I haven't tried them yet.

How to update the position of a drag adorner during WPF drag-n-drop?

I'm using an adorner to show a 'ghost' of the element being dragged...
var adornerLayer = AdornerLayer.GetAdornerLayer(topLevelGrid);
dragAdorner = new DragAdorner(topLevelGrid, itemToDrag);
adornerLayer.Add(dragAdorner);
dragAdorner.UpdatePosition(e.GetPosition(topLevelGrid));
DragDrop.DoDragDrop(sourceItems, viewModel, DragDropEffects.Move);
adornerLayer.Remove(dragAdorner);
itemToDrag = null;
...but I can't find a nice way to update the position of the adorner during the drag. The closest I've got is by setting AllowDrop="true" on the top level grid and giving it a DragOver handler...
private void TopLevelGrid_OnDragOver(object sender, DragEventArgs e)
{
dragAdorner.UpdatePosition(e.GetPosition(topLevelGrid));
}
But this means I don't get the proper DragDropEffects feedback on the cursor, i.e., it always shows the DragDropEffects.Move cursor instead of DragDropEffects.None until I'm over an actual drop target.
Does anyone know a better way to update the adorner position?
There's this (unfortunately only available as a cached version) pretty old blog post from Bea Stollnitz, which pretty much covers your question. It has a nice implementation of drag n drop with an adorner showing a "ghost image".
Basically drag and drop in WPF is quite the complicate procedure that - if you want some custom DragAdorners - involves adding a bunch of attached dependency properties for handling setup of all the events involved and especially for displaying the adorner in a way that doesn't interfere with the dropping code.
Bea's code works by having a helper class that sets the owning Window's DragOver event handler and AllowDrop right before the actual drag drop operation, that way you can control all the moving in between the actual drag source and the drop target.
So, looking closer at Bea's code that redoced was referring to...
I still set AllowDrop="true" on the top level grid and give it a DragOver handler where I can update the adorner position, but I also set the DragDropEffects to None here. Then I just need to add a DragOver handler to the actual drop target to also update the adorner position...and making sure to set e.Handled = true so that the top level grid's handler doesn't just set the effects back to None when I'm over a drop target...
private void TopLevelGrid_OnDragOver(object sender, DragEventArgs e)
{
UpdateDragAdornerPosition(e.GetPosition(topLevelGrid));
e.Effects = DragDropEffects.None;
e.Handled = true;
}
private void DropTarget_OnDragOver(object sender, DragEventArgs e)
{
UpdateDragAdornerPosition(e.GetPosition(topLevelGrid));
e.Handled = true;
}
I know this is an old question, but I ended up asking the same thing recently and then had to answer it myself. I used hooks via p/invoke to get at the native window messages before they were consumed by the drag and drop operation. This let me track the mouse even during drag and drop and without having to set AllowDrop where I didn't want it.
For the full answer (including most of the code I used) you can check out my question:
WPF - Track mouse during Drag & Drop while AllowDrop = False

How easy it really is to implement drag&drop in silverlight?

I am new to silverlight - I've seen the tutorials and all, what I am looking for are high-level steps required to implement drag&drop and maybe a bit of (pseudo)code just to get an idea.
Any help appreciated!
Could you explain exactly what you would like to achieve with drag and drop in Silverlight? The top answer in the question that you linked to links to this page:
http://www.adefwebserver.com/DotNetNukeHELP/Misc/Silverlight/DragAndDropTest/
This contains a sample project with source that implements drag and drop (coincidentally, based on a sample I made for beta 1 of Silverlight 2 :-) ). What about this code is not suitable for your needs?
EDIT:
The basic skeleton of a drag and drop implementation would look like:
bool isDragging = false;
void elementMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (element.CaptureMouse())
{
isDragging = true;
element.MouseMove += elementMouseMove;
//start drag code goes here
}
}
void elementMouseMove(object sender, MouseEventArgs e)
{
//Drag code goes here
}
void element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (isDragging)
{
element.ReleaseMouseCapture();
isDragging = false;
element.MouseMove -= elementMouseMove;
//Drop code goes here
}
}
Add the MouseLeftButtonUp/Down handlers to the element that you want to drag.
In the MouseMove event handler, add the code that you want to execute during the drag: e.g. change Canvas.Top and Canvas.Left to match the mouse position. You can get the mouse position from the event args. You would probably want to get the position relative to the elements container.
In the MouseLeftButtonUp event handler, add the code that would execute when the "drop" occurs. For example, you might want to implement a "recycle bin" that elements can be dragged to. In that case, you would want to know what elements are underneath the mouse at the point of the drop. You can use VisualTreeHelper.FindElementsAtHostCoordinates, passing the mouse position relative to the application's root (use e.GetPosition(null)). Then if your "recycle bin" element is returned by FindElementsInHostCoordinates you know to execute the appropriate action.
Does this help answer you question?
isn't MouseLeftButtonDown where you are supposed to be starting the capture, not on mouseleftbuttonup?

Resources