IsMouseOver和DragLeave无法正常工作

时间:2017-09-11 20:55:59

标签: c# wpf drag-and-drop mouseover

我的UI上有一个网格/面板,可以执行放下操作。该控件是一个Grid,其中包含一些动态创建的内容(如果重要,则包含边框堆栈面板的视图框。)

当我将相关信息拖到网格中时,我希望它能够更改(重新生成)内部内容,当它丢失或离开时,它应该恢复正常。我有'改变'和'退回'的方法工作得很好,但我无法确定何时打电话给他们。

我已在网格上拖动输入并拖动离开事件。输入效果很好,但假不是。一旦鼠标越过网格内部的顶部,它就会触发拖动离开事件,因此它会更改内容(如果将其从子内容中移回,则会再次触发拖动输入并且只是闪烁)

我的第一个想法是确定鼠标是否实际上仍然在网格上并且只是在没有放回内容的情况下放弃。然而,这似乎不起作用。这是我的拖动代码:

        private void Grid_DragLeave(object sender, DragEventArgs e)
    {
        var wizard = DataContext as WizardVM;
        var gd = sender as Grid;

        if (wizard == null || gd == null || gd.IsMouseOver ||
            gd.Children.Cast<FrameworkElement>().Any(x => x.IsMouseOver)) return;

        wizard.Assembly.CollapsePreview();
    }

正如你所看到的,我甚至试图迭代网格的子节点,看看鼠标是否在其中任何一个上都是真的并且丢弃了,但它仍然只是为了所有这些并且崩溃而返回false。我以为IsMouseOver应该告诉我鼠标是否完全结束,即使它是控制之子...

1 个答案:

答案 0 :(得分:0)

好了,经过一些研究,我发现了一些似乎有用的东西。我最终不得不使用VisualTreeHelper.HitTest并使用具有回调的重载并获取所有命中项,即使它被遮挡了。这是我的最终代码:

    void Grid_DragLeave(object sender, DragEventArgs e)
    {
        var wizard = DataContext as WizardVM;
        var gd = sender as Grid;

        if (wizard == null || gd == null) return;
        Point pt = e.GetPosition(this);
        hitResults.Clear();
        VisualTreeHelper.HitTest(gd, null, GridHitTestResultCallback,
            new PointHitTestParameters(pt));

        if (!hitResults.Contains(gd))
        {
            wizard.Assembly.IsExpanded = false;
        }
    }

    HitTestResultBehavior GridHitTestResultCallback(HitTestResult result)
    {
        hitResults.Add(result.VisualHit);
        return HitTestResultBehavior.Continue;
    }

基本上它得到与完整窗口相关的点,然后用该点调用HitTest以及我正在尝试使用的整个网格。回调填充命中测试命中的视觉效果列表。最后,原始方法检查网格是否在命中列表中,如果不是,则将其折叠。

作为附注,我还将.ExpandPreview()和.CollapsePreview()方法更改为.IsExpanded属性,原因无关......不希望任何人对此更改感到困惑......