我有双显示器设置。当我在主显示器上打开应用程序并将其拖动到辅助显示器(在两个显示器的中间)并打开应用程序中的组合框时,即使应用程序移至辅助显示器,它也会在主显示器上打开。
组合框位于主屏幕上,单击鼠标后列表框在辅助屏幕中打开
如果您知道解决此问题的方法,请告诉我。 预先感谢您。
我在这里一无所知。
Popup
实际上是真正的Window
。它与创建它的主屏幕相关联(隐式地通过 ComboBox
)。这就是为什么当您打开 Popup
并开始移动放置目标时,它通常表现得“奇怪”。 Popup
不会跟随。它并非旨在遵循展示位置目标。它是一个独立的“飞行”窗口设计,考虑到了一个非常具体的场景,普通的 Windows(或对话框)无法解决这个问题。通常,您打开它以进行快速操作或简要显示信息(工具提示),并在完成后立即关闭它,至少在将焦点移开时如此。如果您需要像工具箱这样的持久窗口,那么可以使用对话框窗口。关键是 Popup
不遵循放置目标,因此不关心相关的显示更改。Popup
属性)来强制 Popup.HorizontalOffset
更新其位置。HorzontalOffset +=1;
HorizontalOffset -=1;
这应该将
Popup
移动到新屏幕。例如,您可以实现一个附加行为,当托管 Window
移动时修改偏移量。值得一试。我可以提供以下行为进行尝试。要附加它,您必须引用实际的 Popup
元素。为此,您可以覆盖 ControlTemplate
的原始
ComboBox
。
<Popup PopupService.IsSticky="True" />
PopupService.cs
public class PopupService : DependencyObject
{
#region IsFollowPlacementTargetPositionEnabled attached property
public static readonly DependencyProperty IsStickyProperty =
DependencyProperty.RegisterAttached(
"IsSticky",
typeof(bool),
typeof(PopupService),
new PropertyMetadata(default(bool), PopupService.OnIsStickyChanged));
public static void SetIsSticky(DependencyObject attachingElement, bool value)
=>
attachingElement.SetValue(PopupService.IsStickyProperty, value);
public static bool GetIsSticky(DependencyObject attachingElement)
=>
(bool)attachingElement.GetValue(PopupService.IsStickyProperty);
#endregion
private static Dictionary<Window, IList<System.Windows.Controls.Primitives.Popup>> WindowToPopupsMap { get; set; }
static PopupService()
=> PopupService.WindowToPopupsMap = new Dictionary<Window, IList<System.Windows.Controls.Primitives.Popup>>();
private static void OnIsStickyChanged(
DependencyObject attachingElement,
DependencyPropertyChangedEventArgs e)
{
if (attachingElement is not System.Windows.Controls.Primitives.Popup popup)
{
throw new ArgumentException("Attaching element must be of type 'System.Windows.Controls.Primitives.Popup'");
}
bool isEnabled = (bool)e.NewValue;
if (isEnabled)
{
if (!popup.IsLoaded)
{
popup.Loaded += PopupService.EnableFollowTargetMovementOnPopupLoaded;
return;
}
PopupService.EnableFollowTargetMovement(popup);
}
else
{
PopupService.DisableFollowTargetMovement(popup);
}
}
private static void EnableFollowTargetMovementOnPopupLoaded(object sender, RoutedEventArgs e)
=> PopupService.EnableFollowTargetMovement(sender as System.Windows.Controls.Primitives.Popup);
private static void EnableFollowTargetMovement(System.Windows.Controls.Primitives.Popup popup)
{
Window window = PopupService.GetParentWindow(popup);
if (PopupService.WindowToPopupsMap.TryGetValue(window, out IList<System.Windows.Controls.Primitives.Popup> popups)
&& popups != null
&& !popups.Contains(popup))
{
popups.Add(popup);
}
else
{
PopupService.WindowToPopupsMap.Add(window, new List<System.Windows.Controls.Primitives.Popup>() { popup });
}
WeakEventManager<Window, EventArgs>.AddHandler(
window,
nameof(Window.LocationChanged),
PopupService.UpdatePopup_OnParentWindowMoved);
WeakEventManager<Window, SizeChangedEventArgs>.AddHandler(
window,
nameof(FrameworkElement.SizeChanged),
PopupService.UpdatePopup_OnParentWindowSizeChanged);
}
private static void DisableFollowTargetMovement(System.Windows.Controls.Primitives.Popup popup)
{
Window window = PopupService.GetParentWindow(popup);
if (PopupService.WindowToPopupsMap.TryGetValue(window, out IList<System.Windows.Controls.Primitives.Popup> popups)
&& !popups.Contains(popup))
{
_ = popups.Remove(popup);
if (!popups.Any())
{
_ = PopupService.WindowToPopupsMap.Remove(window);
}
}
WeakEventManager<Window, EventArgs>.RemoveHandler(
window,
nameof(Window.LocationChanged),
PopupService.UpdatePopup_OnParentWindowMoved);
WeakEventManager<Window, SizeChangedEventArgs>.RemoveHandler(
window,
nameof(FrameworkElement.SizeChanged),
PopupService.UpdatePopup_OnParentWindowSizeChanged);
}
private static Window GetParentWindow(System.Windows.Controls.Primitives.Popup popup)
{
if (popup.PlacementTarget == null || !popup.PlacementTarget.TryFindVisualParentElement(out Window window))
{
window = Application.Current.MainWindow;
}
return window;
}
private static void UpdatePopup_OnParentWindowMoved(object sender, EventArgs e)
{
var window = sender as Window;
PopupService.UpdatePopupPosition(window);
}
private static void UpdatePopup_OnParentWindowSizeChanged(object sender, SizeChangedEventArgs e)
{
var window = sender as Window;
PopupService.UpdatePopupPosition(window);
}
private static void UpdatePopupPosition(Window window)
{
if (PopupService.WindowToPopupsMap.TryGetValue(window, out IList<System.Windows.Controls.Primitives.Popup> popups))
{
foreach (var popup in popups)
{
popup.HorizontalOffset += 1;
popup.HorizontalOffset -= 1;
}
}
}
}