【问题标题】:WPF C# PreviewDrop/Drop event not fired ( With dragadorner)WPF C# PreviewDrop/Drop 事件未触发(使用 dragadorner)
【发布时间】:2013-08-12 06:31:41
【问题描述】:

我假设 previewdrop/drop 事件是在它检测到一个元素作为放置目标的拖动目标时触发的。在这种情况下,我的放置目标是一个文本框,我的拖动目标是一个标签。它们都是从 DB 动态创建的。我正在使用 DragAdorner 克隆我正在拖动的元素,在实施 DragAdorner 之前,我的 DnD 运行良好,但在我使用 dragadorner 之后,它就不起作用了。当我尝试调试时,我注意到我的 previewdrop 事件没有触发。

这是我的代码:

 tbox.Drop += new DragEventHandler(tbox_PreviewDrop); // text box , Drop Target
 tbox.DragOver += new DragEventHandler(tbox_DragOver);

Label lbl = new Label();  // Label , Drag Target 
             lbl.Content = s;
             lbl.Width = Double.NaN;
             lbl.Height = 40;
             lbl.FontSize = 19;
             lbl.PreviewMouseDown += new MouseButtonEventHandler(lbl_MouseDown);
             lbl.PreviewMouseMove += new MouseEventHandler(lbl_MouseMove);
            lbl.PreviewGiveFeedback += new GiveFeedbackEventHandler(lbl_GiveFeedback);


     private void lbl_MouseDown(object sender, MouseButtonEventArgs e)
    {
        startPoint = e.GetPosition(this);
      //  Mouse.OverrideCursor = Cursors.None;

    }

    private void lbl_MouseMove(object sender, MouseEventArgs e)
    {

        if (e.LeftButton == MouseButtonState.Pressed)
        {

          //  Mouse.OverrideCursor = Cursors.None;

            var source = sender as UIElement;
            Label lbl = sender as Label;
            Point current = e.GetPosition(this);
            Vector diff = startPoint - current;

            if (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
                Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)
            {

                adorner = new DragAdorner(lbl, e.GetPosition(lbl));
                AdornerLayer.GetAdornerLayer(lbl).Add(adorner);

                var dragData = new DataObject(this);
                DragDrop.DoDragDrop(source, dragData, DragDropEffects.Copy);
                AdornerLayer.GetAdornerLayer(lbl).Remove(adorner);

            }
            startPoint = current;
        }
    }

    private void lbl_GiveFeedback(object sender, GiveFeedbackEventArgs e)
    {
        if (adorner != null)
        {
            Label lbl = sender as Label;
            var pos = lbl.PointFromScreen(GetMousePosition());
            adorner.UpdatePosition(pos);
            e.Handled = true;

        }
    }



private void tbox_PreviewDrop(object sender, DragEventArgs e)
        {

            (sender as TextBox).Text = string.Empty; // Empty the textbox from previous answer.
            (sender as TextBox).Background = Brushes.White;
            e.Effects = DragDropEffects.Move;
            e.Handled = true;

        }

        private void tbox_DragOver(object sender, DragEventArgs e)
        {
            e.Handled = true;
            e.Effects = DragDropEffects.Move;

        }
     [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool GetCursorPos(ref Win32Point pt);

    [StructLayout(LayoutKind.Sequential)]
    internal struct Win32Point
    {
        public Int32 X;
        public Int32 Y;
    };

    public static Point GetMousePosition()
    {
        Win32Point w32Mouse = new Win32Point();
        GetCursorPos(ref w32Mouse);
        return new Point(w32Mouse.X, w32Mouse.Y);
    }

    private Point startPoint;
    private DragAdorner adorner;

还有装饰类文件:

 public class DragAdorner : Adorner {

public DragAdorner(UIElement adornedElement, Point offset)

    : base(adornedElement) {

    this.offset = offset;

    vbrush = new VisualBrush(AdornedElement);
    //vbrush.Opacity = .7;

}



public void UpdatePosition(Point location) {

    this.location = location;

    this.InvalidateVisual();

}



protected override void OnRender(DrawingContext dc) {

    var p = location;

    p.Offset(-offset.X, -offset.Y);

    dc.DrawRectangle(vbrush, null, new Rect(p, this.RenderSize));

}



private Brush vbrush;

private Point location;

private Point offset;

}

我见过http://www.adorkable.us/books/wpf_control_development.pdf(第 103 页),但对我来说太复杂了,因为我是新手。

是因为我的 GiveFeedBack 事件与其他事件发生冲突?

【问题讨论】:

    标签: c# wpf events drag-and-drop adorner


    【解决方案1】:

    由于您的DragAdorner 始终在您的光标下,因此它将是接收拖放的对象。如果您在Adorner 的构造函数中设置IsHitTestVisible = false;,它应该可以解决这个问题。

    即使您没有在Adorner 上设置AllowDrop,由于它在光标下,它会拦截放置尝试。但是由于它不接受丢弃,它只会取消它。

    更新

    另一个问题是您将拖动操作中的允许效果设置为DragDropEffects.Copy,但在DragOverDrop 处理程序中,您正在尝试执行DragDropEffects.Move。这是行不通的,因为它们不是相同的操作。这些必须匹配。如果要在拖动时启用这两种操作,可以使用按位或指定两者:

    DragDrop.DoDragDrop(source, dragData, DragDropEffects.Copy | DragDropEffects.Move);
    

    更新 2

    如果您想将除string 之外的任何内容放到TextBox 上,则必须使用PreviewDropPreviewDragOver 事件。否则,TextBox 的默认处理将忽略其他任何内容。所以它看起来像这样:

    tbox.PreviewDrop += new DragEventHandler(tbox_PreviewDrop); 
    tbox.PreviewDragOver += new DragEventHandler(tbox_DragOver);
    

    【讨论】:

    • 嗨,我设置了 IsHitTestVisible = false 。它仍然不会下降。对不起,但我不太明白你关于丢弃尝试和东西的第二句话
    • 基本上,WPF 将在光标位置进行命中测试并尝试放在最顶部的元素上。如果该元素不接受丢弃,则操作将被取消。这就是为什么在您的 Adorner 上禁用命中测试很重要(Adorners 总是在最前面)。
    • 我禁用了 hittest ,不工作,还有其他问题吗?
    • 您好,我试过 Copy 和 Move 一起,也不起作用.. 是因为无法将装饰器拖到文本框中吗?
    • 好吧,使用PreviewDragPreviewDrop,您可以操作数据,以便将您想要的内容放到TextBox 上。但是如果你拖动一个字符串,TextBox 可以自己处理它。
    【解决方案2】:

    尝试为您的标签设置背景颜色,看看它是否能正常工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-15
      • 1970-01-01
      相关资源
      最近更新 更多