2009-10-13 6 views
3

J'applique glisser & drop à partir d'un ListBox, mais je vois un comportement étrange avec un ContextMenu ailleurs dans la fenêtre. Si vous ouvrez le menu contextuel et que vous lancez un glisser depuis le contrôle ListBox, le menu contextuel se ferme mais ne s'ouvrira plus qu'après avoir effectué un autre glisser.WPF ListBox Glisser-déposer interfère avec ContextMenu?

Est-ce que cela a du sens? Quelqu'un a-t-il des idées sur ce qui pourrait se passer?

<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; 
     } 
    } 
} 

Répondre

1

Il semblait être quelque chose à voir avec la capture de la souris !?

La séquence normale des événements au cours d'une traînée va quelque chose comme ça ...

  1. Le gestionnaire PreviewMouseLeftButtonDown est appelé et ListBox.IsMouseCaptureWithin est faux. Le PreviewMouseMove gestionnaire est appelé. À ce moment, ListBox.IsMouseCaptureWithin est vrai.
  2. Pendant le gestionnaire PreviewMouseMove DragDrop.DoDragDrop est appelé et quelque temps au cours de cette capture souris est libéré de la zone de liste.

Mais, ce qui semble se produire pour un frein a commencé quand le menu contextuel est ouvert est ...

  1. Le gestionnaire PreviewMouseLeftButtonDown est appelé et ListBox.IsMouseCaptureWithin est faux. Le gestionnaire PreviewMouseMove obtient le numéro appelé. Mais cette fois ListBox.IsMouseCaptureWithin est encore faux.
  2. Quelque temps après la fin du PreviewMouseMove gestionnaire ListBox obtient alors la capture de la souris (ListBox.IsMouseCaptureWithin devient vrai)

Le résultat de ceci est que, après la traînée, la zone de liste a encore la capture de la souris donc tous les clics sur le bouton pour ouvrir le menu contextuel vont en fait à la liste et non au bouton.

Ajout du code suivant au début du gestionnaire PreviewMouseLeftButtonDown semble aider en avalant le clic qui ferme ce menu contextuel plutôt que d'essayer de commencer une en traîner ...

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

... avec le contextMenuCloseComplete bool se trouvant dans les gestionnaires pour les événements Closed et Opened du menu contextuel.

Est-ce que cela a du sens? Est-ce que quelqu'un comprend d'où vient ce comportement de capture de souris?