2008-10-21 6 views
16

die WPF Popup-Steuerelement ist schön, aber meiner Meinung nach etwas begrenzt. Gibt es eine Möglichkeit, ein Popup beim Öffnen zu "ziehen" (wie bei der DragMove() -Methode von Windows)?Drag WPF Popup-Steuerelement

kann dies ohne große Probleme gemacht werden oder muss ich selbst einen Ersatz für die Popup-Klasse schreiben? danke

Antwort

13

Hier ist eine einfache Lösung mit einem Daumen.

  • Subklassen-Popup in XAML und Code-Behind
  • einen Daumen mit Breite/Höhe hinzufügen auf 0 gesetzt
  • für MouseDown- Veranstaltungen auf der Popup-Listen (dies auch in XAML getan werden könnte) und das gleiche Ereignis erhöht auf die Daumen
  • Verschieben Popup auf 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

Vielleicht fehlt mir etwas einfaches, dass ein erfahrener WPF-Entwickler würde wissen, aber wie ist das wiederverwendbar? Wenn ich das Steuerelement in einem anderen XAML-Kontext einfüge (z. B. wenn ich versuche, es in einem Fenster wiederzuverwenden), überschreibt jeder von mir angegebene Inhalt das Canvas-Element, an das der Daumen gebunden ist. – Vassi

+0

Ich habe diese Lösung ausprobiert. Funktioniert super! Danke Jacob. Ich habe nur ein Problem: Ich habe eine Ansicht innerhalb dieses Daumens und kann die gesamte Ansicht fein ziehen. Wenn diese Ansicht jedoch über eine Bildlaufleiste verfügt, verursacht das Ziehen der Bildlaufleiste das Ziehen des Daumens und damit der gesamten Ansicht. Gibt es eine Möglichkeit, dies zu vermeiden? – Shankar

16

Es gibt kein DragMove für PopUp. Nur eine kleine Arbeit, es gibt viele Verbesserungen, die Sie hinzufügen können. out

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

In der Code-behind, fügen Sie dieses mousemove- Ereignis

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

** ** Ouch! Nein, verwenden Sie stattdessen ein ['Thumb'] (http://msdn.microsoft.com/en-us/library/ms749252%28VS.100%29.aspx) und dessen' DragDelta' Event (opt. 'DragStarted'/'DragCompleted', wenn Sie Zustände verwalten wollen. Es ist viel effizienter, wird das Gedächtnis nicht fragmentieren und wird nicht riskieren, die Maus als das Beispiel oben zu verlieren. So wird das Ziehen richtig gemacht :) Sehen Sie [hier] (http://www.codeproject.com/KB/WPF/TubePlanner.aspx) für ein Beispiel. – RedGlyph

+0

Ich stimme zu, dass die Lösung, die ich gegeben habe, nur ein Hack ist. Wie Sie sagten, DragDelta ist leistungsfähiger als MoveMove. –

+1

Aber was, wenn du ein Popup nicht als Daumen missbrauchen willst (was ich in RedGlyphs Kommentar meinte), aber ein komplexeres Popup (z. B. Video-Overlay) verschieben möchtest. Verwenden eines expliziten Fensters ist keine Option in meinem Szenario. –

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

Das für das Ziehen meines Fensters funktioniert, aber wie es gesagt wurde, wenn ich die Maus schnell bewegen, würde es bekommen von Fenster und hör auf, das Ereignis zu erhöhen. Ohne zu erwähnen, ist das Ziehen überhaupt nicht glatt. Weiß jemand, wie man es richtig macht, schönes und sanftes Ziehen, ohne es zu verlieren, wenn es zu schnell gezogen wird ??? Poste ein einfaches Beispiel, wenn möglich, abgesehen von einem ganzen Tutorial, das Anfänger wie mich im Code verlieren würde. Vielen Dank!

+0

Sie könnten die Maus erfassen, um das Problem zu vermeiden, das Sie erwähnt haben, wenn die Maus aus dem Fenster kommt –

2

Eine andere Möglichkeit, dies zu erreichen, besteht darin, das Popup-Placement auf MousePoint zu setzen. Dadurch erscheint das Popup zunächst an der Position des Mauszeigers.

Dann können Sie entweder ein Thumb- oder MouseMove-Ereignis verwenden, um den HorizontalOffset & VerticalOffset des Popups festzulegen. Diese Eigenschaften verschieben das Popup von seiner ursprünglichen Position weg, wenn der Benutzer es zieht.

Denken Sie daran, HorizontalOffset und VerticalOffset für die nächste Verwendung des Popup auf Null zurückzusetzen!

2

Das Problem mit der Maus zu verlieren, wenn sie zu schnell bewegen,

aufgelöst werden konnte

Der von Msdn genommen wird:

Das neue Fenster enthält das Kind Inhalt von Popup.

Das Popup-Steuerelement verwaltet einen Verweis auf seinen Child-Inhalt als logisches Kind. Wenn das neue Fenster erstellt wird, wird der Inhalt von Popup ein visuelles Kind des Fensters und bleibt das logische untergeordnete Element von Popup. Umgekehrt bleibt Popup das logische übergeordnete Element seines Child-Inhalts.


In den anderen Worten, das Kind des Popup wird im Standalone-Fenster angezeigt.

Also beim Versuch, Folgendes zu tun:
Popup.CaptureMouse() erfasst das Wrapper-Fenster und nicht das Popup-Fenster selbst. Stattdessen verwendet Popup.Child.CaptureMouse() das aktuelle Popup.

Und alle anderen Ereignisse sollten mit Popup.Child registriert werden.

Wie Popup.Child.MouseMove, Popup.Child.LostCapture und so weiter

Dies wurde getestet und arbeitet völlig in Ordnung

+0

Ja, das Erfassen der Mauseingabe ist die richtige Methode zum Ziehen. All dies e.Leftbutton == Gepresst ist ein bisschen faul und verursacht einige Nebenwirkungen. – Alan

Verwandte Themen