2008-10-21 76 views
16

WPF彈出控件很好,但在我看來有點受限。有沒有辦法在打開時拖動一個彈出窗口(就像使用Windows的DragMove()方法)?拖動WPF彈出控件

可以在此沒有大的問題做或做我必須寫在彈出類自己的替代品? 感謝

回答

13

下面是使用Thumb的簡單解決方案。在XAML

  • 子類彈出和隱藏代碼
  • 添加一個拇指設置爲0寬/高(這也可以在XAML完成)
  • 監聽在彈出的MouseDown事件,並提出同樣的事件上在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; 
     }; 
    } 
} 
16

沒有爲彈出沒有DragMove。只是一個小小的工作,你可以添加很多改進。

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

在後面的代碼,添加此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

** **哎呦!不,請使用[`Thumb`](http://msdn.microsoft.com/en-us/library/ms749252%28VS.100%29.aspx)及其`DragDelta`事件(選擇「DragStarted」/「 `DragCompleted`,如果你想管理狀態)。它更高效,不會像以上例子那樣碎片化內存,並且不會冒失去鼠標的風險。這就是正確的拖動方式:)例子見[這裏](http://www.codeproject.com/KB/WPF/TubePlanner.aspx)。 – RedGlyph 2010-09-02 19:37:33

+0

我同意,我給出的解決方案只是一個破解,正如你所說DragDelta比MoveMove更高效。 – 2010-09-02 21:16:44

+1

但是,如果你不想濫用彈出窗口作爲拇指(我想我的意思是在RedGlyphs評論中),但想要移動更復雜的彈出窗口(例如視頻覆蓋圖)。在我的場景中使用明確的窗口不是選項。 – 2011-07-26 13:39:57

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

這適用於拖我的窗口,但就像是如果我把鼠標移動到快告訴,它會走出的窗口,並停止提高事件。沒有提到拖拽根本不流暢。有誰知道如何正確地做到這一點,漂亮和平滑的拖動,而不會拖動太快拖動它?如果可能的話發佈一個簡單的例子,除了可以讓像我這樣的初學者在代碼中丟失的整個教程。謝謝!

+0

你可以捕捉鼠標,以避免你提到的問題,當鼠標離開窗口 – 2011-05-02 11:02:55

2

實現這一目標的另一種方法是設置彈出窗口的位置,以MousePoint。這使彈出窗口最初出現在鼠標光標的位置。

那麼您可以使用拇指或MouseMove事件,設置彈出的Horizo​​ntalOffset & VerticalOffset。這些屬性會在用戶拖拽Popup時將其從原始位置移開。

記住將Horizo​​ntalOffset和VerticalOffset回零,以便下次使用彈出窗口!

2

與失去鼠標的問題走得太快時,能夠得到解決


這是從MSDN採取:

新窗口包含兒童Popup的內容。

彈出式窗口控制,以保持它的子內容的邏輯子對象的引用。當新窗口被創建時,彈出窗口的內容變成窗口的可視子窗口,並保持爲彈出窗口的邏輯子窗口。相反,Popup仍然是其子內容的合乎邏輯的父項。


在換句話說,在彈出的子顯示在獨立的窗口。

因此,當嘗試以下操作:
Popup.CaptureMouse()正在捕獲包裝窗口,而不是彈出窗口本身。而是使用Popup.Child.CaptureMouse()捕獲實際的彈出窗口。

所有其他事件都應該使用Popup.Child註冊。

Popup.Child.MouseMovePopup.Child.LostCapture

這已經過測試,運行完美