WPF Drag & drop from ListBox with SelectionMode Multiple

前端 未结 4 1304
后悔当初
后悔当初 2020-12-29 22:47

I\'ve almost got this working apart from one little annoying thing...

Because the ListBox selection happens on mouse down, if you start the drag with the mouse down

4条回答
  •  难免孤独
    2020-12-29 23:12

    So...having become the proud owner of a tumbleweed badge, I've got back on to this to try & find a way around it. ;-)

    I'm not sure I like the solution so I'm still very much open to any better approaches.

    Basically, what I ended up doing is remember what ListBoxItem was last clicked on & then make sure that gets added to the selected items before a drag. This also meant looking at how far the mouse moves before starting a drag - because clicking on a selected item to unselect it could sometimes result in it getting selected again if mouse bounce started a little drag operation.

    Finally, I added some hot tracking to the listbox items so, if you mouse down on a selected item it'll get unselected but you still get some feedback to indicate that it will get included in the drag operation.

    private void HandleLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var source = (FrameworkElement)sender;
        var hitItem = source.InputHitTest(e.GetPosition(source)) as FrameworkElement;
        hitListBoxItem = hitItem.FindVisualParent();
        origPos = e.GetPosition(null);
    }
    private void HandleLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        hitListBoxItem = null;
    }
    private void HandleMouseMove(object sender, MouseEventArgs e)
    {
        if (ShouldStartDrag(e))
        {
            hitListBoxItem.IsSelected = true;
    
            var sourceItems = (FrameworkElement)sender;
            var viewModel = (WindowViewModel)DataContext;
            DragDrop.DoDragDrop(sourceItems, viewModel, DragDropEffects.Move);
            hitListBoxItem = null;
        }
    }
    private bool ShouldStartDrag(MouseEventArgs e)
    {
        if (hitListBoxItem == null)
            return false;
    
        var curPos = e.GetPosition(null);
        return
      Math.Abs(curPos.Y-origPos.Y) > SystemParameters.MinimumVerticalDragDistance ||
      Math.Abs(curPos.X-origPos.X) > SystemParameters.MinimumHorizontalDragDistance;
    }
    

    XAML changes to include hot tracking...

    
    

提交回复
热议问题