Avalonia.Xaml.Behaviors icon indicating copy to clipboard operation
Avalonia.Xaml.Behaviors copied to clipboard

[Improvement] `ListBox.draggable`-Style should not disable virtualization

Open timunie opened this issue 2 years ago • 14 comments

Hi @wieslawsoltes

first of all this library is really really useful and I am happy with the state it is. 😄 However when I tested some performance in my App and I noticed that adding several hundred or thousand items to a ListBox.draggable makes the UI nearly unusable. After having a deeper look I noticed that virtualization is disabled in the Styles-Section:

  <Style Selector=":is(ListBox).draggable">
    <Setter Property="ItemsPanel">
      <Setter.Value>
        <ItemsPanelTemplate>
          <StackPanel Orientation="Vertical" />
        </ItemsPanelTemplate>
      </Setter.Value>
    </Setter>
  </Style>

If I replace the StackPanel with VirtualizingStackPanel it works, but dragging an item and scrolling is buggy (I think this is the reason for disabling virtualization?)

I know that I can add my own logic which I already do (I use adorner instead of transforms) but maybe others will face the same issue also, that is why I decided to open this ticket here. If I find a good solution I'll open a PR for this.

Happy coding Tim

timunie avatar Nov 22 '21 20:11 timunie

If I replace the StackPanel with VirtualizingStackPanel it works, but dragging an item and scrolling is buggy (I think this is the reason for disabling virtualization?)

@timunie What bugs do you see when you use VirtualizingStackPanel ?

wieslawsoltes avatar Nov 25 '21 12:11 wieslawsoltes

Hi @wieslawsoltes

see the video below to get an impression of what I see. Animation1

I created a sample branch here: https://github.com/timunie/AvaloniaBehaviors/tree/issue/VirtualizationIssue

Happy coding Tim

timunie avatar Nov 25 '21 14:11 timunie

@timunie Thanks for repro. I am working on fix and other improvements here https://github.com/wieslawsoltes/AvaloniaBehaviors/pull/85

wieslawsoltes avatar Nov 25 '21 23:11 wieslawsoltes

That is great news 🙂. If I can do anything to test or support please let me know.

timunie avatar Nov 26 '21 05:11 timunie

@timunie Can you check https://github.com/wieslawsoltes/AvaloniaBehaviors/pull/85 if this fixes the issues.

I have added draggableVirtualizing style to enable virtualization.

wieslawsoltes avatar Nov 26 '21 22:11 wieslawsoltes

Hi @wieslawsoltes,

sorry for the late response. I tested the latest master as #85 was already merged. I still see the issue why I thought virtualization cannot be fully supported. It is not about applying the VirtualizationStackPanel, that I was able to do already. The things are getting broken once the user scrolls while dragging. If you have a long list you may want to drag the selected item to a position which is not yet in the visible area. So you press the mouse, start dragging and while you still press the mouse you may turn the mouse wheel. This brings two issues:

  1. The dragged item is no longer under your pointer position,
  2. The dragged container may change its content

I think the root cause for what I see are two different things

  1. Issue 1 may be fixed by a different RederTransform-Calculation
  2. Issue 2 seems to happen because of the container recycling. And I don't have a good idea for this. That is why I ended up with using Adorner instead.

How do you wish to proceed (I am happy with any choise you make as I am able to implement a solution on my end which suits my needs)

  1. Open this issue again to track the issues mentioned above
  2. I can also open a new issue instead
  3. Leave the code as it is now as the things I observe are not a common issue / not a real world problem

Thank you for your efforts and happy coding Tim

timunie avatar Nov 28 '21 08:11 timunie

Hi @wieslawsoltes,

sorry for the late response. I tested the latest master as #85 was already merged. I still see the issue why I thought virtualization cannot be fully supported. It is not about applying the VirtualizationStackPanel, that I was able to do already. The things are getting broken once the user scrolls while dragging. If you have a long list you may want to drag the selected item to a position which is not yet in the visible area. So you press the mouse, start dragging and while you still press the mouse you may turn the mouse wheel. This brings two issues:

  1. The dragged item is no longer under your pointer position,
  2. The dragged container may change its content

I think the root cause for what I see are two different things

  1. Issue 1 may be fixed by a different RederTransform-Calculation
  2. Issue 2 seems to happen because of the container recycling. And I don't have a good idea for this. That is why I ended up with using Adorner instead.

How do you wish to proceed (I am happy with any choise you make as I am able to implement a solution on my end which suits my needs)

  1. Open this issue again to track the issues mentioned above
  2. I can also open a new issue instead
  3. Leave the code as it is now as the things I observe are not a common issue / not a real world problem

Thank you for your efforts and happy coding Tim

Did you use draggableVirtualizing class?

wieslawsoltes avatar Nov 28 '21 09:11 wieslawsoltes

I tested it in your demo App with the latest master

timunie avatar Nov 28 '21 09:11 timunie

I double checked and it is the virtualized style. Are you able to scroll while dragging?

timunie avatar Nov 28 '21 09:11 timunie

I double checked and it is the virtualized style. Are you able to scroll while dragging?

I was able to scroll and drag, didn't notice issues. Can you record the issue on your machine ?

wieslawsoltes avatar Nov 28 '21 10:11 wieslawsoltes

Sure

Here is the branch I checked out. Should be the latest master: image

And here is a video showing the issue. I annotated a few frames in order to be more clear what I noticed.

https://user-images.githubusercontent.com/47110241/143765356-23248bed-71b9-4761-9479-a822a3e39820.mp4

timunie avatar Nov 28 '21 11:11 timunie

Hi @wieslawsoltes

Today I tested it on a different machine with the same results.

Tested it with:

  • both machines running Windows 10
  • both having a graphic card if this matters
  • Tested with Visual Studio
  • Tested with Rider
  • Tested without Debugger

I have no idea why I see such a different result than you do. All I can offer is a video call to demonstrate it live, but I know that you have much to do and my issue is not an issue for most users.

Have a great evening and happy coding Tim

timunie avatar Nov 29 '21 18:11 timunie

Hi @wieslawsoltes

Today I tested it on a different machine with the same results.

Tested it with:

  • both machines running Windows 10
  • both having a graphic card if this matters
  • Tested with Visual Studio
  • Tested with Rider
  • Tested without Debugger

I have no idea why I see such a different result than you do. All I can offer is a video call to demonstrate it live, but I know that you have much to do and my issue is not an issue for most users.

Have a great evening and happy coding Tim

I think it requires handling item container generator event (materialize, dematerialize etc.) and handle new containers.

wieslawsoltes avatar Nov 29 '21 19:11 wieslawsoltes

I think it requires handling item container generator event (materialize, dematerialize etc.) and handle new containers.

Yes, maybe that is a good idea to do. I have to learn more about this

I think the scrolling needs to be handled also in some way as the RenderTransform needs to be adjusted accordingly.

timunie avatar Nov 30 '21 09:11 timunie