2011-03-27 15 views
14

Obtengo DragLeave Events al arrastrar desde un control principal al secundario. Solo esperaría obtener este evento cuando se mueva fuera de los límites de un control. ¿Cómo puedo implementar esto?WPF Drag Drop - ¿Cuándo DragLeave Fire?

Consulte esta sencilla aplicación de muestra.

<Window x:Class="MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525"> 
    <StackPanel> 
     <TextBox Height="50" >Hilight and Drag this text</TextBox> 
     <Border BorderBrush="Blue" BorderThickness="2"> 
      <StackPanel AllowDrop="True" Name="Stack" > 
       <Label >If I drag text across the gray line, Stack.DragLeave will fire.</Label> 
       <Separator></Separator> 
       <Label>I only expect to get this event when leaving the blue rectangle. </Label> 
      </StackPanel> 
     </Border> 
     <TextBlock >Stack.DragLeave Count: <Label x:Name="countLabel" /></TextBlock> 
    </StackPanel> 
</Window> 

y en el código detrás

Class MainWindow 

    Private Sub Stack_DragLeave(ByVal sender As Object, ByVal e As System.Windows.DragEventArgs) Handles Stack.PreviewDragLeave 
     countLabel.Content = countLabel.Content + 1 
    End Sub 

End Class 

enter image description here

+0

posible duplicado de [DragDrop - DragEnter/Eventos DragLeave seguir disparando] (http://stackoverflow.com/questions/2632821/dragdrop-dragenter-dragleave-events-keep -firing) –

Respuesta

17

Recientemente he estado trabajando en mi propia aplicación que está usando WPF arrastrar/soltar extensamente y después de pasar medio día (depuración , googleando, volviendo a leer la documentación) exactamente sobre el mismo problema que está viendo, solo pude concluir que hay una "mejora futura" enterrada en algún lugar de la biblioteca de WPF.

Esta fue mi solución:

protected virtual void OnTargetDragLeave(object sender, DragEventArgs e) 
    { 
     _dragInProgress = false; 

     // It appears there's a quirk in the drag/drop system. While the user is dragging the object 
     // over our control it appears the system will send us (quite frequently) DragLeave followed 
     // immediately by DragEnter events. So when we get DragLeave, we can't be sure that the 
     // drag/drop operation was actually terminated. Therefore, instead of doing cleanup 
     // immediately, we schedule the cleanup to execute later and if during that time we receive 
     // another DragEnter or DragOver event, then we don't do the cleanup. 
     _target.Dispatcher.BeginInvoke(new Action(()=> { 
           if(_dragInProgress == false) OnRealTargetDragLeave(sender, e); })); 
    } 

    protected virtual void OnTargetDragOver(object sender, DragEventArgs e) 
    { 
     _dragInProgress = true; 

     OnQueryDragDataValid(sender, e); 
    } 
+0

Gracias DXM, esto parece solucionar el problema para la gran mayoría de los controles de los niños. Sin embargo, al arrastrar el control del separador (y quizás también a otros), se invoca el método OnQueryDragDataValid. – PeterM

+1

@Peter, la llamada a OnQueryDragDataValid() que agregué allí fue para mi implementación específica. No creo que deba estar allí, si no lo necesitas. Mi diseño (y creo que WPF también lo quiere de esa manera) era que OnQueryDragDataValid() se puede llamar cualquier cantidad de veces y simplemente necesita verificar que la operación de descarte sea válida. – DXM

+0

@DMX, sí, estás absolutamente en lo cierto. Quise escribir que OnRealTargetDragLeave se dispara al arrastrar sobre un control de separación. Creo que esto se debe a que "los controles de Separator no reaccionan a ninguna entrada de teclado, mouse, mouse o tableta y no se pueden habilitar ni seleccionar (desde MSDN)". Sin embargo, los separadores pueden reemplazarse fácilmente con otros controles similares (línea, rectángulo, etc.) que funcionarán. ¡Gracias de nuevo por el gran trabajo! – PeterM

Cuestiones relacionadas