我正在实施拖拽从ListBox中删除,但我在窗口的其他地方看到了ContextMenu的一些奇怪行为。如果打开上下文菜单然后从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;
}
}
}
答案 0 :(得分:1)
这似乎与鼠标捕获有关!?
拖动过程中正常的事件序列就像这样......
PreviewMouseLeftButtonDown
处理程序被调用
ListBox.IsMouseCaptureWithin
是
假的。PreviewMouseMove
处理程序
被叫。到了这个时候
ListBox.IsMouseCaptureWithin
是真的。PreviewMouseMove
处理程序中
DragDrop.DoDragDrop
被调用了
在此期间的某个时候鼠标
捕获从ListBox中释放。但是,当上下文菜单打开时,似乎发生的阻力似乎是......
PreviewMouseLeftButtonDown
处理程序被调用
ListBox.IsMouseCaptureWithin
是
假的。PreviewMouseMove
处理程序获取
调用。但这一次
ListBox.IsMouseCaptureWithin
是
仍然是假的。PreviewMouseMove
处理程序
ListBox然后获取鼠标捕获
(ListBox.IsMouseCaptureWithin
变得真实)这样做的结果是,在拖动之后,ListBox仍然具有鼠标捕获功能,因此任何打开上下文菜单的按钮实际上都会转到列表框而不是按钮。
将以下代码添加到PreviewMouseLeftButtonDown
处理程序的开头似乎有助于吞掉关闭该上下文菜单的点击,而不是试图从它开始拖动......
if (!contextMenuCloseComplete)
{
sourceElement.CaptureMouse();
return;
}
...将contextMenuCloseComplete
bool设置为上下文菜单Closed
和Opened
事件的处理程序。
这有意义吗?有谁知道这种鼠标捕获行为的来源?