【问题标题】:Can't get simple WPF drag and drop to work无法让简单的 WPF 拖放工作
【发布时间】:2010-11-22 14:35:49
【问题描述】:

对于一个简单的测试,我想将一个按钮拖到一个文本框。我可以开始拖动 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;
    }
}

【问题讨论】:

  • 您没有设置拖动效果。类似 e.Effects = DragDropEffects.Copy;在您的 DragEnter 处理程序中将起作用。

标签: wpf drag-and-drop


【解决方案1】:

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

这里是如何使它工作的。

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

【讨论】:

  • +1,这是一个很大的帮助。对我来说,我缺少的是new DataObject(...)——以前我直接使用一个对象,它的Type作为键,这显然不起作用:-)
【解决方案2】:

我相信这与当您启动拖动事件时,按钮控件正在捕获鼠标输入这一事实有关。之后您所做的任何鼠标移动都会注册到按钮而不是应用程序

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

【讨论】:

  • 嗨,我有类似的情况,有什么可以参考的。
  • @Eldho This answer 在 SO 上帮助我朝着正确的方向前进
  • 谢谢,但我的不同,我有两个数据网格,其中 1 个包含按钮和切换按钮,我想将整行拖放到第二个数据网格。问题是当在 ROW 的 BUTTON / CHECKBOX 上选择时我无法拖动,只有在 Border 上选择才能使拖动工作,我想拖动整行甚至单击 BUTTON。
  • @Eldho 尝试使用 PreviewMouseDown 而不是 MouseDown 或 MouseClick 事件。如果这不起作用,我建议您提出一个新问题,列出您的代码、您正在尝试做什么、正在发生的事情以及您已经尝试过的事情:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-20
  • 2012-09-07
  • 2015-07-09
  • 2013-01-06
  • 1970-01-01
相关资源
最近更新 更多