2008-10-21 16 views
16

el control WPF Popup es bueno, pero algo limitado en mi opinión. ¿Hay alguna manera de "arrastrar" una ventana emergente cuando se abre (como con el método de ventanas DragMove())?Arrastre WPF Popup control

¿se puede hacer esto sin grandes problemas o tengo que escribir un sustituto para la clase emergente yo mismo? gracias

Respuesta

13

Aquí hay una solución simple con un pulgar.

  • Subclase emergente en XAML y código subyacente
  • Añadir un pulgar con anchura/altura se establece en 0 (esto también se podría hacer en XAML)
  • Escuchar los eventos MouseDown en la ventana emergente y elevar el mismo evento en el pulgar
  • movimiento emergente en DragDelta

XAML:

<Popup x:Class="PopupTest.DraggablePopup" ...> 
    <Canvas x:Name="ContentCanvas"> 

    </Canvas> 
</Popup> 

C#:

public partial class DraggablePopup : Popup 
{ 
    public DraggablePopup() 
    { 
     var thumb = new Thumb 
     { 
      Width = 0, 
      Height = 0, 
     }; 
     ContentCanvas.Children.Add(thumb); 

     MouseDown += (sender, e) => 
     { 
      thumb.RaiseEvent(e); 
     }; 

     thumb.DragDelta += (sender, e) => 
     { 
      HorizontalOffset += e.HorizontalChange; 
      VerticalOffset += e.VerticalChange; 
     }; 
    } 
} 
+0

Quizás me esté perdiendo algo simple que un desarrollador avezado de WPF sabría, pero ¿cómo se puede reutilizar? Cuando siembro el control en un contexto XAML diferente (como intentar reutilizarlo en una ventana), cualquier contenido que especifique sobreescribe el elemento Canvas al que está vinculado el thumb. – Vassi

+0

He intentado esta solución. ¡Funciona genial! Gracias Jacob. Me enfrenta solo a un problema: tengo una vista dentro de este Thumb y puedo arrastrar toda la vista, sin embargo, si esa vista tiene una barra de desplazamiento, al arrastrar la barra de desplazamiento está arrastrando el pulgar y, por lo tanto, toda la vista. Hay alguna manera de evitar esto? – Shankar

16

No hay DragMove para PopUp. Solo un pequeño trabajo, hay muchas mejoras que puede agregar a esto.

<Popup x:Name="pop" IsOpen="True" Height="200" Placement="AbsolutePoint" Width="200"> 
    <Rectangle Stretch="Fill" Fill="Red"/>    
</Popup> 

En el código subyacente, agregue este evento mousemove

pop.MouseMove += new MouseEventHandler(pop_MouseMove); 

    void pop_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (e.LeftButton == MouseButtonState.Pressed) 
     { 
      pop.PlacementRectangle = new Rect(new Point(e.GetPosition(this).X, 
       e.GetPosition(this).Y),new Point(200,200)); 

     } 
    } 
+16

** ** Ay! No, use un ['Thumb'] (http://msdn.microsoft.com/en-us/library/ms749252%28VS.100%29.aspx) y su evento' DragDelta' en su lugar (opt. 'DragStarted'/'DragCompleted' si desea administrar estados). Es mucho más eficiente, no fragmentará la memoria y no correrá el riesgo de perder el mouse como el ejemplo anterior. Así es como se realiza el arrastre correctamente :) Consulte [aquí] (http://www.codeproject.com/KB/WPF/TubePlanner.aspx) para ver un ejemplo. – RedGlyph

+0

Estoy de acuerdo, esa solución que he dado es solo un truco, Como dijiste, DragDelta es más eficiente que MoveMove. –

+1

Pero, ¿y si no quieres utilizar mal una ventana emergente como un pulgar (que supongo que quise decir en el comentario de RedGlyphs), pero quieres mover una ventana emergente más compleja (por ejemplo, superposición de video). usar una ventana explícita no es una opción en mi escenario. –

0
Private Point startPoint; 

private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 

     startPoint = e.GetPosition(null); 
    } 
private void Window_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (e.LeftButton == MouseButtonState.Pressed) 
     { 
      Point relative = e.GetPosition(null); 
      Point AbsolutePos = new Point(relative.X + this.Left, relative.Y + this.Top); 
      this.Top = AbsolutePos.Y - startPoint.Y; 
      this.Left = AbsolutePos.X - startPoint.X; 
     } 
    } 

Esto funciona para arrastrar mi ventana, pero como se dijo a si muevo el ratón para ayunar, sería salir de ventana y deja de plantear el evento. Sin mencionar que el arrastre no es suave en absoluto. ¿Alguien sabe cómo hacerlo de manera adecuada, agradable y sin problemas arrastrando, sin perderlo cuando se arrastra demasiado rápido? Publique un ejemplo simple si es posible, aparte de un tutorial completo que permita que los principiantes como yo se pierdan en el código. ¡Gracias!

+0

podría capturar el mouse para evitar el problema que mencionó cuando el mouse se sale de la ventana –

2

Otra forma de lograr esto es establecer la ubicación de su ventana emergente en MousePoint. Esto hace que la ventana emergente aparezca inicialmente en la posición del cursor del mouse.

Luego puede usar un evento Thumb o MouseMove para establecer el Offset Horizontal & VerticalOffset de la ventana emergente. Estas propiedades desplazan el Popup lejos de su posición original mientras el usuario lo arrastra.

¡Recuerde restablecer HorizontalOffset y VerticalOffset de vuelta a cero para el siguiente uso de la ventana emergente!

2

El problema con perder el ratón cuando se mueve demasiado rápido, podría ser resuelto


Esto está tomado de MSDN:

La nueva ventana contiene Niño contenido de Popup.

El control Popup mantiene una referencia a su contenido secundario como un elemento secundario lógico. Cuando se crea la nueva ventana, el contenido de Popup se convierte en un elemento visual de la ventana y sigue siendo el elemento lógico de Popup. Por el contrario, Popup sigue siendo el padre lógico de su contenido secundario.


En las otras palabras, el niño de la ventana emergente aparece en la ventana independiente.

Al intentar hacer lo siguiente:
Popup.CaptureMouse() está capturando la ventana contenedora y no la ventana emergente. En cambio, al usar Popup.Child.CaptureMouse(), se captura la ventana emergente real.

Y todos los demás eventos deben registrarse usando Popup.Child.

Como Popup.Child.MouseMove, Popup.Child.LostCapture y así sucesivamente

Esto ha sido probado y funciona perfectamente bien

+0

Sí, capturar la entrada del mouse es la forma correcta de manejar el arrastre. Todo esto e.Leftbutton == Presionado es un poco flojo y causa algunos efectos secundarios. – Alan