user2376998
user2376998

Reputation: 1071

Drag and Drop with Drag Adorner

i used a drag adorner to clone the image of my labels ( drag target ) but however now i couldn't drop my label into my textbox ,

this is the code i have used ( u might see theres previewdragover , i wrote e.Handled = true in previewdragover but doesn't help ) i have also set tbox.AllowDrop to true :

TextBox :

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

Handlers for textbox :

   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 ( drag target ) :

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

Handlers for label :

        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;

Now i can drag the labels with the labels following my cursor but i can't drop them in any textbox.

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

I have put a dragenter for textbox like this :

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

    }

Still not working tho.

i'll add the DragAdorner.cs here that i've used ( i got it from some chinese web ) :

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;

Upvotes: 5

Views: 11391

Answers (3)

Job
Job

Reputation: 41

The problem is that your drag adorner is always on top. When you try to drop your label it drops on the adorner instead of the underlying component.

To avoid this add the following line to the constructor of the DragAdorner.

IsHitTestVisible = false;

Upvotes: 4

Fou Lou
Fou Lou

Reputation: 1

Initialize your Dragadorner with Point(-5,-5). (new DragAdorner(new Point(-5,-5));)

The drop Event seems to be thrown on the Adorner. If you add a drop handler to the Adorner youll see that it gets called when you release the mouse.

It seems that the Mouse pointer is over the Adorner and it takes it as Target.

Setting the offset to a Point so that the Adorner is not under the Mousepointer corrects that behavior.

Upvotes: 0

Sheridan
Sheridan

Reputation: 69959

Your code is somewhat different to my working example, but I think that I can see your problem. In my code, I have a method called UpdateDragDropEffects. This method takes in an object of type DragEventArgs named e and updates the e.Effects property dependent on the value of the e.AllowedEffects property and also whether I have a valid ICommand instance to call and whether the data is of the expected type, etc.

This method is called (and the DragEventArgs object passed from) two typical drag and drop methods; DragTargetPreviewDrop (handles the PreviewDrop event) and AdornedUIElementPreviewDragOver (handles the PreviewDragOver event). Setting the e.Effects property of the DragEventArgs object tells the system whether the current drag opearation is valid and should continue or not... not setting it, or setting it to DragDropEffects.None will have the effect of not displaying any valid drop targets.

The Drag and Drop Overview page at MSDN has code examples that should also help you. The Enabling an Element to be a Drop Target section has example code that shows what I have described.

You could also have other problems, but come back and update if this doesn't help you.

Upvotes: 0

Related Questions