使用拖动装饰器拖放

时间:2013-08-05 08:39:12

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

我使用拖动装饰来克隆我的标签图像(拖动目标)但是现在我无法将我的标签放入我的文本框中,

这是我使用的代码(你可能会看到theres previewdragover,我在previewdragover中写了e.Handled = true但没有帮助)我也将tbox.AllowDrop设置为true:

TextBox:

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

文本框处理程序:

   protected 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.Handled = true;
    }

标签(拖动目标):

             Label lbl = new Label();
             lbl.Content = s;
             lbl.Width = Double.NaN;
             lbl.Height = 40;
             lbl.FontSize = 19;
             lbl.MouseDown += new MouseButtonEventHandler(lbl_MouseDown);
             lbl.MouseMove += new MouseEventHandler(lbl_MouseMove);
             lbl.GiveFeedback += new GiveFeedbackEventHandler(lbl_GiveFeedback);
             lbl.MouseUp += new MouseButtonEventHandler(lbl_MouseUp); 
             wrapPanel2.Children.Add(lbl);

标签处理程序:

        private void lbl_MouseUp(object sender, MouseButtonEventArgs e)
    {
        Mouse.OverrideCursor = Cursors.Arrow;
    }

    private void lbl_MouseDown(object sender, MouseButtonEventArgs e)
    {
        startPoint = e.GetPosition(this);

    }

    private void lbl_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {


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

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

现在我可以使用光标后面的标签拖动标签,但我不能将它们放在任何文本框中。

----- EDIT ------------

我为这样的文本框添了一个dragenter:

       private void tbox_PreviewDragEnter(object sender, DragEventArgs e)
    {
        if (sender == e.Source)
        {
            e.Effects = DragDropEffects.None;
        }

    }

仍然没有工作。

我将在这里添加DragAdorner.cs(我从一些中文网站获得):

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;

3 个答案:

答案 0 :(得分:3)

问题在于您的拖拽装饰器始终位于顶部。当您尝试删除标签时,它会落在装饰器而不是底层组件上。

为避免这种情况,请将以下行添加到DragAdorner的构造函数中。

  

IsHitTestVisible = false;

答案 1 :(得分:0)

您的代码与我的工作示例略有不同,但我认为我可以看到您的问题。在我的代码中,我有一个名为UpdateDragDropEffects的方法。此方法接收名为DragEventArgs的{​​{1}}类型的对象,并根据e属性的值更新e.Effects属性,以及我是否具有有效{{1}调用实例以及数据是否属于预期类型等。

调用此方法(并传递e.AllowedEffects对象)两种典型的拖放方法; ICommand(处理DragEventArgs事件)和DragTargetPreviewDrop(处理PreviewDrop事件)。设置AdornedUIElementPreviewDragOver对象的PreviewDragOver属性会告诉系统当前的拖动操作是否有效并且是否应该继续...不设置它,或者将其设置为e.Effects将具有不显示任何有效放置目标的效果。

MSDN上的Drag and Drop Overview页面有代码示例,也可以帮助您。 DragEventArgs部分的示例代码显示了我所描述的内容。

您可能还有其他问题,但如果这对您没有帮助,请回来更新。

答案 2 :(得分:0)

使用Point(-5,-5)初始化Dragadorner。 (new DragAdorner(new Point(-5,-5));)

放下事件似乎是在Adorner上引发的。如果您向Adorner添加放置处理程序,则会在释放鼠标时看到它被调用。

似乎鼠标指针位于Adorner上方并将其作为Target。

将偏移设置为Point,以便Adorner不在Mousepointer下,可以纠正该行为。