2013-08-12 3 views
5

Я предполагаю, что события предварительного просмотра/кавычки запускаются, когда он обнаруживает цель перетаскивания с элементом в качестве цели перетаскивания. В этом случае моя целевая точка перехода является текстовым полем, а моя цель перетаскивания - это метка. Оба они динамически создаются из БД. Я использую DragAdorner для клонирования элемента, который я перетаскиваю, прежде чем реализовать DragAdorner, мой DnD работает хорошо, но после того, как я использую dragadorner, это не сработает. И я замечаю, что мое событие previewdrop не срабатывает, когда я пытаюсь отлаживать.WPF C# PreviewDrop/Drop событие не запускается (с помощью dragadorner)

Вот мои коды:

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; 

А класс 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, которое противоречит другим событиям?

ответ

3

Поскольку ваш DragAdorner всегда находится под вашим курсором, это будет объект, получающий падение. Если вы установили IsHitTestVisible = false; в конструктор для Adorner, он должен исправить это.

Даже если вы не установили AllowDrop на Adorner, так как он находится под курсором, он перехватит попытку сбрасывания. Но поскольку он не принимает падение, он просто отменит его.

Update

Другой вопрос заключается в том, что вы устанавливаете допустимые эффекты на операции перетаскивания для DragDropEffects.Copy, но в DragOver и Drop обработчиков, что вы пытаетесь сделать DragDropEffects.Move. Это не сработает, так как это не такая же операция. Они должны совпадать. Если вы хотите, чтобы включить обе операции на сопротивление, вы можете указать, как с побитовое или:

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

Update 2

Если вы хотите что-либо иное, чем string падение на TextBox, у вас есть для использования событий PreviewDrop и PreviewDragOver. В противном случае обработка по умолчанию TextBox игнорирует все остальное. Так будет выглядеть так:

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

привет, я установил IsHitTestVisible = false. он все равно не упадет. Извините, но я не совсем понимаю ваше второе предложение о попытке сбрасывания и материалах – user2376998

+0

В принципе, WPF выполнит тест попадания в месте расположения курсора и попытается упасть на самый верхний элемент. Если этот элемент не принимает капли, операция будет отменена. Вот почему важно отключить тестирование ударов на вашем «Adorner» («Adorner's always on top»). –

+0

У меня отключен hittest, не работает, есть ли другие проблемы? – user2376998

0

Попробуйте установить цвет фона для своей этикетки и посмотреть, будет ли она работать должным образом.

+0

to transparent? не работает. – user2376998

+0

нет прозрачный, только цвет – mat

+0

тоже не работает/ – user2376998