无法让简单的WPF拖放工作

时间:2010-11-22 14:35:50

标签: wpf drag-and-drop

对于简单的测试,我想将Button拖动到TextBox。我可以开始拖动Button,但不会引发Drop事件。我错过了什么?

的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>

代码:

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;
    }
}

2 个答案:

答案 0 :(得分:2)

我认为这与启动拖动事件时按钮控件捕获鼠标输入的事实有关。之后执行的任何鼠标移动都会注册到按钮而不是应用程序

我实际上遇到了类似的问题,并最终使用了MouseEnter / Leave事件而不是内置的WPF拖放框架。

答案 1 :(得分:2)

这可能是一些奇怪的情况,但要修复它,我需要处理或拖动事件,包括预览版本。

以下是如何使其发挥作用。

的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>

代码:

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;
    }
}