簡體   English   中英

用鼠標拖動彈出窗口

[英]Dragging a Popup with the mouse

我有以下行為可以從這里用鼠標拖動彈出窗口

wpf中的可拖動彈出控件

public class MouseDragPopupBehavior : Behavior<Popup>
{
    private bool mouseDown;
    private Point oldMousePosition;

    protected override void OnAttached()
    {
        AssociatedObject.MouseLeftButtonDown += (s, e) =>
        {
            mouseDown = true;
            oldMousePosition = AssociatedObject.PointToScreen(e.GetPosition(AssociatedObject));
            AssociatedObject.Child.CaptureMouse();
        };
        AssociatedObject.MouseMove += (s, e) =>
        {
            if (!mouseDown) return;
            var newMousePosition = AssociatedObject.PointToScreen(e.GetPosition(AssociatedObject));
            var offset = newMousePosition - oldMousePosition;
            oldMousePosition = newMousePosition;
            AssociatedObject.HorizontalOffset += offset.X;
            AssociatedObject.VerticalOffset += offset.Y;
        };
        AssociatedObject.MouseLeftButtonUp += (s, e) =>
        {
            mouseDown = false;
            AssociatedObject.Child.ReleaseMouseCapture();
        };
    }
}

這有效,但是當我使用自定義放置到 position 時,移動不是 1:1 window 右下角的彈出窗口。

public class MyPopup : Popup
{
...
    CustomPopupPlacementCallback += (Size popupSize, Size targetSize, Point offset) =>
    {
        offset.X += targetSize.Width - popupSize.Width - 50;
        offset.Y += targetSize.Height - popupSize.Height - 100;
        return new[] { new CustomPopupPlacement(offset, PopupPrimaryAxis.Horizontal) };
    };
}

彈出窗口比鼠標移動得更多,最終 cursor 不再位於彈出窗口之上。

我如何調整此代碼,使彈出窗口與 cursor 完全一致?

我相信這兩者不能很好地協同工作,主要是因為在CustomPopupPlacementCallback案例中有一些關於如何選擇放置的重要邏輯。

您觀察到的行為是因為您在此處增加偏移量:

offset.X += targetSize.Width - popupSize.Width - 50;
offset.Y += targetSize.Height - popupSize.Height - 100;

該偏移量是您根據拖動行為設置的HorizontalOffsetVerticalOffset 但是您期望從該自定義回調中返回的是相對 position,因此您不需要為其添加偏移量。 例如,這將修復它:

var x = targetSize.Width - popupSize.Width - 50;
var y = targetSize.Height - popupSize.Height - 100;
return new[] { new CustomPopupPlacement(new Point(x, y), PopupPrimaryAxis.Vertical) };

但是,無論如何,在屏幕邊緣附近,您都會在多顯示器設置中遇到問題(與您現在遇到的問題不同)。 執行拖動時也會多次調用此回調,影響性能。

我建議只在打開時放置一次彈出窗口。 將 Placement 設置為Relative並根據需要設置PlacementTarget (可能您已經這樣做了),然后只需計算打開時的偏移量。 您可以在拖動行為本身中執行此操作(當然它不再只是拖動行為,但我不會在這里使用干凈的編碼實踐):

AssociatedObject.Opened += (o, e) => {
    var popupRoot = (FrameworkElement)AssociatedObject.Child;
    var target = (FrameworkElement)AssociatedObject.PlacementTarget; // you can use "constraint" from other question here
    AssociatedObject.HorizontalOffset = target.ActualWidth - popupRoot.ActualWidth - 50;
    AssociatedObject.VerticalOffset = target.ActualHeight - popupRoot.ActualHeight - 100;
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM