2009-10-13 62 views
3

我正在實現從列表框中拖放&拖放,但我在窗口中的其他地方看到了一些與ContextMenu有關的奇怪行爲。如果您打開上下文菜單,然後從ListBox開始拖動,上下文菜單將關閉,但直到執行另一次拖動之後纔會再次打開。WPF ListBox拖放干擾ContextMenu?

這是否有意義?任何人有什麼想法可能會發生什麼?

<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

這似乎是與鼠標捕獲!?

事件的拖動過程中的正常順序是這樣的......

  1. PreviewMouseLeftButtonDown 處理程序被調用和 ListBox.IsMouseCaptureWithin是 假的。
  2. PreviewMouseMove處理程序 被調用。此時 ListBox.IsMouseCaptureWithin爲真。
  3. PreviewMouseMove處理程序 DragDrop.DoDragDrop被調用期間和 在此期間,鼠標 捕獲從列表框中釋放。

但是,什麼似乎發生了拖拽開始時的上下文菜單打開時...

  1. PreviewMouseLeftButtonDown 處理程序被調用和 ListBox.IsMouseCaptureWithin是 假的。
  2. PreviewMouseMove處理程序獲取 調用。但這一次 ListBox.IsMouseCaptureWithin是 仍然是錯誤的。
  3. 有時的 PreviewMouseMove結束後處理程序則 ListBox中獲取鼠標捕獲 (ListBox.IsMouseCaptureWithin 爲真)

這樣做的結果是,拖動後,列表框仍然具有鼠標捕獲所以任何點擊按鈕打開上下文菜單實際上是去列表框而不是按鈕。

添加以下代碼到PreviewMouseLeftButtonDown處理程序的開始似乎被吞噬了封閉該上下文菜單,而不是試圖從它開始拖動點擊幫助......

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

...與contextMenuCloseComplete布爾設置處理程序的上下文菜單的ClosedOpened事件。

這有道理嗎?有沒有人知道這個鼠標捕獲行爲來自哪裏?