c# - 用鼠标拖动弹出窗口
问题描述
我有以下行为从这里用鼠标拖动弹出窗口
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();
};
}
}
这可行,但是当我使用自定义放置将弹出窗口定位在窗口的右下角时,移动不是 1:1。
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) };
};
}
弹出窗口比鼠标移动更多,最终光标不再位于弹出窗口上方。
如何调整此代码,使弹出窗口与光标完全移动?
解决方案
我相信这两者不能很好地协同工作,主要是因为有一些关于如何选择放置CustomPopupPlacementCallback
以防万一的逻辑。
您观察到的行为是因为您在此处增加了偏移量:
offset.X += targetSize.Width - popupSize.Width - 50;
offset.Y += targetSize.Height - popupSize.Height - 100;
这个偏移量是HorizontalOffset
你VerticalOffset
从拖动行为中设置的。但是您希望从该自定义回调返回的是相对位置,因此您不需要为其添加偏移量。例如,这将解决它:
var x = targetSize.Width - popupSize.Width - 50;
var y = targetSize.Height - popupSize.Height - 100;
return new[] { new CustomPopupPlacement(new Point(x, y), PopupPrimaryAxis.Vertical) };
但是,无论如何,在屏幕边缘附近的多显示器设置中,您都会遇到问题(与您现在遇到的问题不同)。拖拽时也会多次调用该回调,影响性能。
我建议改为只放置一次弹出窗口,打开。将 PlacementRelative
设置为并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;
};
推荐阅读
- python - Python Selenium find_element_by_link_text 不适合我
- c# - .NET Core 5 Web 应用程序中具有复杂 json 值的 Http GET 请求
- ruby-on-rails - Rails 5:如何将此 named_scope 转换为范围
- activemq - Red Hat AMQ 6.3 相互认证将用户映射到证书
- python - 创建一个列出所有先前整数之和的生成器函数
- r - 调整ggplot代码以更改所有文本颜色的快捷方式-R
- d3.js - d3.scaleLinear() 导致 TypeError: r is not a function
- r - 列表列表的一个向量的平均值
- swift - 在 macOS 上运行 SwiftUI 应用程序,但该平台被识别为 iOS。为什么?
- google-api - Google Places API 提取返回状态:200 但没有数据