【问题标题】:WPF DragEnter between two Canvas not firing两个 Canvas 之间的 WPF DragEnter 未触发
【发布时间】:2012-07-03 07:18:56
【问题描述】:

我正在尝试将一个项目从一个画布拖到另一个画布上。我希望在对象进入另一个画布时触发一个事件。似乎没有任何 Drag 事件触发。 我已经尝试按照这个问题的解决方案,但它对我不起作用: Drag and Drop not responding as expected

我的画布是这样的:

<Window x:Class="DragEnterTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="DragEnterMainWindow" Height="460" Width="1000">
<Grid>
    <Canvas Name="Toolbox" Background="Beige" Height="400" Width="200" Margin="12,12,800,35">
        <Rectangle Name="dragRectangle" Canvas.Left="0" Canvas.Right="0" Width="50" Height="50" Fill="Red"
                   MouseLeftButtonDown="dragRectangle_MouseLeftButtonDown"
                   MouseLeftButtonUp="dragRectangle_MouseLeftButtonUp"
                   MouseMove="dragRectangle_MouseMove"
                   />
    </Canvas>
    <Canvas Background="Azure" Height="400" Margin="218,12,0,35" Name="mainCanvas" Panel.ZIndex="-1"
            DragEnter="mainCanvas_DragEnter"
            DragLeave="mainCanvas_DragLeave"
            PreviewDragEnter="mainCanvas_PreviewDragEnter"
            PreviewDragLeave="mainCanvas_PreviewDragLeave"
            AllowDrop="True"
            DragDrop.Drop="mainCanvas_Drop"
            />
</Grid>
</Window>

如果我没有 Panel.ZIndex="-1",则将矩形拖到 mainCanvas 下方。即使我将矩形的 ZIndex 设置为某个正值也是如此。

我的代码如下,由我找到的示例修改:

namespace DragEnterTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private bool _isRectDragInProg;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void dragRectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _isRectDragInProg = true;
        dragRectangle.CaptureMouse();
    }

    private void dragRectangle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        _isRectDragInProg = false;
        dragRectangle.ReleaseMouseCapture();
    }

    private void dragRectangle_MouseMove(object sender, MouseEventArgs e)
    {
        if (!_isRectDragInProg) return;
        // get the position of the mouse relative to the Canvas
        var mousePos = e.GetPosition(Toolbox);

        // center the rect on the mouse
        double left = mousePos.X - (dragRectangle.ActualWidth / 2);
        double top = mousePos.Y - (dragRectangle.ActualHeight / 2);
        Canvas.SetLeft(dragRectangle, left);
        Canvas.SetTop(dragRectangle, top);
    }

    private void mainCanvas_DragEnter(object sender, DragEventArgs e)
    {
        string t = "Test";  // Never enters this event
    }

    private void mainCanvas_DragLeave(object sender, DragEventArgs e)
    {
        string t = "Test";  // Never enters this event
    }

    private void mainCanvas_PreviewDragEnter(object sender, DragEventArgs e)
    {
        string t = "Test";  // Never enters this event
    }

    private void mainCanvas_PreviewDragLeave(object sender, DragEventArgs e)
    {
        string t = "Test";  // Never enters this event
    }

    private void mainCanvas_Drop(object sender, DragEventArgs e)
    {
        string t = "Test";  // Never enters this event
    }
}

}

【问题讨论】:

    标签: wpf canvas drag-and-drop dragenter


    【解决方案1】:

    您实际上并没有拖动任何东西,只是在画布中到处移动矩形。

    当您的矩形离开源时,您需要调用DragDrop.DoDragDrop 函数,并将其与源分离,以便稍后将其添加到目标。

        // Drag - In mousemove event when mouse has gone out of toolbox
        DragDrop.DoDragDrop(
            Toolbox, 
            new DataObject("MyWPFObject", rectangle),
            DragDropEffects.Move
        );
    
        // Drop - In Drop event of target
        if (e.Data.GetDataPresent("MyWPFObject"))
        { 
           var rectangle = e.Data.GetData("MyWPFObject") as Rectangle
        ....
    

    Tutorial ...

    【讨论】:

    • 感谢您的快速回答。我还没有让它与我真正想要的东西一起工作(我的例子很简单)。看来我必须自己编写很多代码。但是您的简单解释非常有助于让我更多地了解什么构成拖放(在 WPF 中)。为此,我感谢你。
    【解决方案2】:

    我相信这是因为您正在捕获鼠标,所以所有鼠标事件都由您拖动的Rectangle 处理,它们不会传递给您的Canvas

    我个人在使用 WPF 的内置拖放功能时遇到了各种问题,所以我最终改用了MouseEvents

    我使用的解决方案来自this answer,结果如下:

    1. MouseDown 上按下左键,记录位置(在MouseLeave 上擦除位置)

    2. MouseMove 上,如果左键按下,则记录位置,并且当前鼠标位置的差异超过 delta,设置一个标志,表示正在进行拖动操作并让您的应用程序(而不是拖动的对象)捕获鼠标

    3. MouseMove 正在进行拖动操作时,使用命中测试来确定您的矩形应该在哪里(忽略矩形本身)并相应地调整其父级和位置。

    4. MouseUp 正在进行拖动操作时,释放鼠标捕获并清除“正在进行拖动操作”标志

    【讨论】:

    • 嗨,瑞秋,谢谢您的回答。我不明白您在第三点中提到的小组。你的意思是矩形,还是需要一些我不知道的面板?还有你的第二点:让你的应用程序捕获鼠标:你有一些例子吗?我不知道你在这里是什么意思。在实际程序中,我正在创建一个看起来相同但有自己事件的对象,我正在拖放的是这个对象(但前提是它落在正确的画布上,否则它应该消失)。
    • @user1497953 抱歉,应该是 Rectangle 而不是 Panel。我会更新它。此外,您当前的代码已拖动 Rectangle 捕获鼠标,因此任何鼠标事件都仅由 Rectangle 对象处理。我正在查看我的一些旧代码,我有一个注释掉了所有鼠标捕获语句,另一个使用 e.MouseDevice.Capture(this as IInputElement); 其中e 是来自MouseMove 事件的MouseEventArgs,而thisApplication.Current.MainWindow
    • 您好,我只是以默认方式使用事件 - 因此我无法从您所写的内容中收集到正确的结构。您(或任何人)是否知道一些关于如何在另一个上下文中捕获事件的参考资料? (升级事件?)我仍然希望能够在可能相同的众多元素中获得单个移动的元素(并且与拖动的元素重叠)。再次感谢您。
    • @user1497953 我从Bea Stollnitz's article on dragging/dropping databound items开始。我强烈建议您检查一下 - 也许它可以为您指明解决方案。
    猜你喜欢
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多