2

我正在编写一个具有按钮网格的 WPF 应用程序,我希望允许用户在网格之间拖放按钮,可能在应用程序的不同实例之间。我尝试通过在按钮上的 PreviewMouseMove 事件中添加一个处理程序,然后在鼠标左键按下时调用 DoDragDrop 来做到这一点,但是当我拖放按钮时,它总是最终调用 DoDragDrop 两次和 drop 事件处理程序两次. 有谁知道为什么会发生这种情况以及如何防止它?

下面是一些演示问题的示例 XAML:

<Window x:Class="WpfTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <DockPanel>
        <Button PreviewMouseMove="PreviewMouseMove" x:Name="m_button" Width="250">
            Hello, world!
        </Button>
        <Label Drop="Drop" AllowDrop="True">
            Drop here!
        </Label>
    </DockPanel>
</Window>

和相应的代码:

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

    private void PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            ++m_dragIndex;
            System.Console.WriteLine("Dragged: " + m_dragIndex.ToString());
            DragDrop.DoDragDrop(m_button, m_dragIndex, DragDropEffects.All);
            e.Handled = true;
        }
    }

    private void Drop(object sender, DragEventArgs e)
    {
        System.Console.WriteLine("Dropped: " + e.Data.GetData(typeof(Int32)).ToString());
    }

    private int m_dragIndex;
}

对于单次拖动,这将被写入输出:

Dragged: 1
Dragged: 2
Dropped: 2
Dropped: 1

更新:我已经更改了上面的示例代码,以显示当按钮被拖放到某物上时会调用哪些拖放事件。

更新:更新了问题以包括在容器和应用程序实例之间拖动,因为这是使用 DragDrop 系统的激励因素。

4

2 回答 2

1

我找到了一个解决方法——因为第一个 DoDragDrop 在内部调用第二个 PreviewMouseMove,我可以跟踪我是否已经在 PreviewMouseMove 调用中,如果我在,则忽略它。这似乎有点讨厌,所以我希望有更好的解决方案。

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

    private void PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if(!m_inMouseMove)
        {
            m_inMouseMove = true;
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                ++m_dragIndex;
                System.Console.WriteLine("Dragged: " + m_dragIndex.ToString());
                DragDrop.DoDragDrop(m_button, m_dragIndex, DragDropEffects.All);
                e.Handled = true;
            }
            m_inMouseMove = false;
        }
    }

    private void Drop(object sender, DragEventArgs e)
    {
        System.Console.WriteLine("Dropped: " + e.Data.GetData(typeof(Int32)).ToString());
    }

    private int m_dragIndex;
    bool m_inMouseMove;
}
于 2013-04-03T06:47:38.530 回答
0

我有同样的问题。我发现 PreviewMouseMove 调用了两次,因为它第一次是由容器元素(例如 ListViewItem)引发的,第二次是针对 TextBlock 的。因此,我可以建议检查 e.OriginalSource 值的类型作为此问题的另一种解决方法。

于 2014-02-22T20:44:41.600 回答