4

For a simple test I want to drag a Button to a TextBox. I can start dragging the Button, but the Drop event is not raised. What am I missing?

Xaml:

<Window x:Class="DayPlanner.View.DnDTest"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DnDTest" Height="200" Width="200">
    <StackPanel>
        <Button Name="button" 
                Content="OK" 
                PreviewMouseLeftButtonDown="button_PreviewMouseLeftButtonDown" 
                PreviewMouseMove="button_PreviewMouseMove"/>
        <TextBox Name="textBox"
                 AllowDrop="True"
                 DragEnter="textBox_DragEnter"
                 Drop="textBox_Drop"/>
    </StackPanel>
</Window>

Code:

public partial class DnDTest : Window
{
    public DnDTest()
    {
        InitializeComponent();
    }

    private Point dragStartPoint;

    private void button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        dragStartPoint = e.GetPosition(null);
    }

    private static bool IsDragging(Point dragStartPoint, MouseEventArgs e)
    {
        var diff = e.GetPosition(null) - dragStartPoint;
        return
            e.LeftButton == MouseButtonState.Pressed &&
            (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
                Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance);
    }

    private void button_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (IsDragging(dragStartPoint, e))
        {
            DragDrop.DoDragDrop(button, new DataObject("Button", button), DragDropEffects.Move);
            e.Handled = true;
        }
    }

    private void textBox_DragEnter(object sender, DragEventArgs e)
    {
        e.Handled = true;
    }

    private void textBox_Drop(object sender, DragEventArgs e)
    {
        var button = (Button)e.Data.GetData("Button");
        textBox.Text = string.Format("[0]", button.Content.ToString());
        e.Handled = true;
    }
}
Stefan
  • 4,166
  • 3
  • 33
  • 47
  • You are not setting the drag effect. Something like e.Effects = DragDropEffects.Copy; in your DragEnter handler would work. – genus Feb 28 '13 at 23:07

2 Answers2

3

This might be some strange case, but to fix it, I needed to handle or dragging events, including the Preview versions.

Here's how to make it work.

Xaml:

<Window x:Class="DayPlanner.View.DnDTestBasic"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DnDTestBasic" Height="200" Width="200">
    <StackPanel>
        <Button Name="button" 
                Content="OK" 
                PreviewMouseLeftButtonDown="button_PreviewMouseLeftButtonDown" 
                PreviewMouseMove="button_PreviewMouseMove"/>
        <TextBox Name="textBox"
                 AllowDrop="True"
                 PreviewDragEnter="textBox_Dragging"
                 DragEnter="textBox_Dragging"
                 PreviewDragOver="textBox_Dragging"
                 DragOver="textBox_Dragging"
                 Drop="textBox_Drop"/>
        <TextBlock Name="status"
                   Text="No dragging"/>
    </StackPanel>
</Window>

Code:

public partial class DnDTestBasic : Window
{
    public DnDTestBasic()
    {
        InitializeComponent();
    }

    private Point dragStartPoint;

    private void button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        dragStartPoint = e.GetPosition(null);
        status.Text = "New drag start position";
    }

    private static bool IsDragging(Point dragStartPoint, MouseEventArgs e)
    {
        var diff = e.GetPosition(null) - dragStartPoint;
        return
            e.LeftButton == MouseButtonState.Pressed &&
            (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
             Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance);
    }

    private void button_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (IsDragging(dragStartPoint, e))
        {
            status.Text = "Starting drag...";
            DragDrop.DoDragDrop(button, new DataObject("Button", button), DragDropEffects.Copy);
            status.Text = "Dragging done.";
            e.Handled = true;
        }
    }

    private void textBox_Dragging(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent("Button"))
            e.Effects = DragDropEffects.Copy;
        else
            e.Effects = DragDropEffects.None;
        e.Handled = true;
    }

    private void textBox_Drop(object sender, DragEventArgs e)
    {
        var button = (Button)e.Data.GetData("Button");
        textBox.Text = string.Format("[{0}]", button.Content.ToString());
        e.Handled = true;
    }
}
Stefan
  • 4,166
  • 3
  • 33
  • 47
  • +1, this was a great help. For me, what I was missing was the `new DataObject(...)` -- previously I was using an object directly, with its `Type` as the key, which apparently doesn't work :-) – Cameron Jan 31 '14 at 15:37
2

I believe it has to do with the fact that when you start the drag event, the button control is capturing mouse input. Any mouse movements you do after that are registered to the button instead of to the application

I actually had a similar problem and ended up using MouseEnter/Leave events instead of the built in WPF drag/drop framework.

Rachel
  • 130,264
  • 66
  • 304
  • 490
  • Hi ,i have similar scenario is there any reference i can look. – Eldho Jul 22 '14 at 05:52
  • @Eldho [This answer](http://stackoverflow.com/a/2639399/302677) on SO helped me out a lot with going in the right direction – Rachel Jul 22 '14 at 11:18
  • Thanks , But mine is different , i have two datagrid's which 1 contains button and toggle button , i want to drag-drop the entire row to the 2nd Data grid . The problem is i could not Drag when the selecting on BUTTON / CHECKBOX of the ROW , ONLY selecting on Border makes the Dragging Work ,I want to Drag entire row even clicking on the BUTTON. – Eldho Jul 22 '14 at 12:39
  • @Eldho Try using PreviewMouseDown instead of MouseDown or MouseClick events. If that doesn't work, I'd recommend asking a new question that lists your code, what you're trying to do, what is happening, and what you've tried already :) – Rachel Jul 22 '14 at 13:38