gpt4 book ai didi

WPF ListBox 拖放会干扰 ContextMenu?

转载 作者:行者123 更新时间:2023-12-02 08:43:38 29 4
gpt4 key购买 nike

我正在从列表框实现拖放,但我在窗口其他位置的上下文菜单中看到一些奇怪的行为。如果您打开上下文菜单,然后从 ListBox 开始拖动,则上下文菜单将关闭,但在您执行另一次拖动之前不会再次打开。

这有道理吗?有人知道会发生什么吗?

<ListBox Grid.Row="0" ItemsSource="{Binding SourceItems}" MultiSelectListboxDragDrop:ListBoxExtension.SelectedItemsSource="{Binding SelectedItems}" SelectionMode="Multiple" PreviewMouseLeftButtonDown="HandleLeftButtonDown" PreviewMouseLeftButtonUp="HandleLeftButtonUp" PreviewMouseMove="HandleMouseMove"/>
<ListBox Grid.Row="1" ItemsSource="{Binding DestinationItems}" AllowDrop="True" Drop="DropOnToDestination" />
<Button Grid.Row="2">
<Button.ContextMenu>
<ContextMenu x:Name="theContextMenu">
<MenuItem Header="context 1"/>
<MenuItem Header="context 2"/>
<MenuItem Header="context 3"/>
</ContextMenu>
</Button.ContextMenu>
Button with context menu
</Button>

...

public partial class Window1
{
private bool clickedOnSourceItem;

public Window1()
{
InitializeComponent();

DataContext = new WindowViewModel();
}

private void DropOnToDestination(object sender, DragEventArgs e)
{
var viewModel = (WindowViewModel)e.Data.GetData(typeof(WindowViewModel));
viewModel.CopySelectedItems();
}

private void HandleLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var sourceElement = (FrameworkElement)sender;
var hitItem = sourceElement.InputHitTest(e.GetPosition(sourceElement)) as FrameworkElement;

if(hitItem != null)
{
clickedOnSourceItem = true;
}
}

private void HandleLeftButtonUp(object sender, MouseButtonEventArgs e)
{
clickedOnSourceItem = false;
}

private void HandleMouseMove(object sender, MouseEventArgs e)
{
if(clickedOnSourceItem)
{
var sourceItems = (FrameworkElement)sender;
var viewModel = (WindowViewModel)DataContext;

DragDrop.DoDragDrop(sourceItems, viewModel, DragDropEffects.Move);
clickedOnSourceItem = false;
}
}
}

最佳答案

好像和鼠标捕获有关!?

拖动过程中事件的正常顺序是这样的......

  1. PreviewMouseLeftButtonDown处理程序被调用并且ListBox.IsMouseCaptureWithin 是错误。
  2. PreviewMouseMove 处理程序被叫。到了这个时候ListBox.IsMouseCaptureWithin 为 true。
  3. PreviewMouseMove 处理程序期间DragDrop.DoDragDrop 被调用并且在此期间的某个时候,鼠标捕获已从列表框中释放。

但是,当上下文菜单打开时开始拖动似乎发生的事情是......

  1. PreviewMouseLeftButtonDown处理程序被调用并且ListBox.IsMouseCaptureWithin 是错误。
  2. PreviewMouseMove 处理程序获取叫。但这一次ListBox.IsMouseCaptureWithin 是仍然是假的。
  3. 结束后的某个时间PreviewMouseMove 处理程序ListBox然后获取鼠标捕获(ListBox.IsMouseCaptureWithin成为现实)

这样做的结果是,拖动后,列表框仍然具有鼠标捕获,因此任何单击按钮以打开上下文菜单的操作实际上都会进入列表框而不是按钮。

将以下代码添加到 PreviewMouseLeftButtonDown 处理程序的开头似乎有助于吞下关闭该上下文菜单的点击,而不是尝试从中开始拖动...

if (!contextMenuCloseComplete)
{
sourceElement.CaptureMouse();
return;
}

...在上下文菜单的 ClosedOpened 事件的处理程序中设置 contextMenuCloseComplete bool。

这有道理吗?有谁知道这种鼠标捕获行为从何而来?

关于WPF ListBox 拖放会干扰 ContextMenu?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1558932/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com