punker76 / gong-wpf-dragdrop

The GongSolutions.WPF.DragDrop library is a drag'n'drop framework for WPF
BSD 3-Clause "New" or "Revised" License
2.29k stars 401 forks source link

Initiating Drag for Multiple Items Snaps Scroll Bar #241

Closed airbreather closed 6 years ago

airbreather commented 7 years ago

We first saw this in our application, but we found a repro in the Showcase app so we figured it's probably a Gong thing.

Here's a video repro: https://youtu.be/9Ivnshr_IEE

What steps will reproduce this issue?

  1. Start the Showcase app... it defaults to ListBox / Bound today, which is just fine.
  2. Uncheck "IsDropTarget" (not strictly required as it happens when the list is a drop target as well, but it stops items from moving around which helps keep things consistent while you try different combinations of stuff).
  3. Shrink the window vertically somewhat, so that you get a scroll bar on the right.
  4. Scroll the far right scroll bar down somewhat.
  5. Using Ctrl+LeftClick, select multiple items in the ListBox.
  6. Start dragging one of the items.

Notice: as soon as you start dragging, the scroll bar on the far right jumps to a very specific location. If it doesn't jump, try again but leaving the scroll bar at a different place in step 4.

Expected outcome

That scroll bar on the right doesn't feel like it should jump around when we start a drag.

Interestingly enough, this only happens the first time you initiate a drag with multiple things selected, and it does not happen when just a single item is selected.

Repo

This one (https://github.com/punker76/gong-wpf-dragdrop)

Environment

punker76 commented 7 years ago

@airbreather This was hard to find, but I can say this is not a problem of this library. The inner ScrollContentPresenter of the ScrollViewer gets also a RequestBringIntoView if you click or drag&drop items of the two ListBoxes. Then the two ListBoxes are will be positioned in this ScrollViewer. You can handle this only by

    public ListBoxSamples()
    {
      InitializeComponent();
      this.Loaded += ListBoxSamples_Loaded;
    }

    private void ListBoxSamples_Loaded(object sender, RoutedEventArgs e)
    {
      var p = TestScrollViewer.GetVisualDescendent<ScrollContentPresenter>();
      p.RequestBringIntoView += FrameworkElement_OnRequestBringIntoView;
    }

    private void FrameworkElement_OnRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
    {
      e.Handled = true;
    }
punker76 commented 7 years ago

@airbreather Do you need more help? Or can I close this?

airbreather commented 7 years ago

I haven't had the opportunity to seriously play with that to figure out what downsides there might be if we just suppress all RequestBringIntoView events. I can't rule them out analytically... I'm not sure if, e.g., automated UI actions that initiate a drag for something that's off-screen would be adversely affected.