WPF ScrollViewer for ListBox -> Performance issues - c#

I'm trying to create grid with listbox with Scrollbar.
It's done somehow like that:
<Grid>
<ListBox Name="xxx" ItemsSource="{Binding}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Visible">
....
</ListBox>
</Grid>
The problem is that if I use scrollbar, then the size of bar-button jumps back and forward within scrolling. If I remove ScrollViewer from properties and instead put ListBox in ScrollViewer tag, then everything is working perfect, except of terrible performance of rerendering UI (resize, move window, resource consuming). According to google it does "disable virtualization". This sounds crazy that there's no simple solution to get properly working scrollbar and usable UI without issues.
Is there compromise for both of these things? Virtualization + properly working scrollviewer with fixed size of scrollbar button.

Related

UWP GridView - How to maintain visible items upon resizing (Column count changes)

I have a GridView that I use to display thousands of images/thumbnails (using data binding). I used ImplicitAnimations to add transitions, so that when the control is resized and the number of columns changes - every item smoothly goes into the new position after the resize.
Problem
This all works fine when the user is at the top of the GridView but becomes a problem the further the user scrolls. The further you scroll, the more items are moved around when the number of columns changes. More rows are added/removed, but the Scrollbar is kept on the same position/offset which causes previously visible items to go far away from the view - and the user gets lost.
What I tried so far...
I tried working around this issue by tracking the first visible item on every scroll change event and then scrolling to it on SizeChanged event. The problem of this solution, however, is that it's really rough. Animations are no longer noticable and the whole experience is laggy.
Is there any better solution to this problem?
Illustration of the problem
Video example
I have also made a video to better illustrate the issue.
(The images have been blurred because some were NSFW)
Video Link
What I am looking for is a way for the scrollbar to adjust it's position on resize and stay on the same items the User was looking at - without messing up the animations.
Edit
So apparently this can't be solved any other way but manually scrolling to the item I wish to have visible on resize, which I already tried doing and had problems with the animations being really rough again because the ScrollToItem was happening AFTER the animations were being triggered.
So my question now is - can I scroll to an item on reorder/resize - BEFORE the animations get triggered? That way I think I could keep the smoothness. Using the resize event, however, doesn't work for this.
Edit 2 - Code sample
<GridView x:Name="mylist" animations:ReorderGridAnimation.Duration="600" ItemsSource="{Binding Source={StaticResource viewSource}}">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" HorizontalAlignment="Center" Loaded="ItemsWrapGrid_Loaded"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<Grid Width="300" Height="300" Background="Gainsboro">
<Image Source="{Binding ThumbnailImage}" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
GridView ItemSource is binded to the following CollectionView
<UserControl.Resources>
<controls:AdvancedCollectionView x:Key="viewSource" Source="{x:Bind Collection}" />
</UserControl.Resources>
I switched to the Community Toolkit for the animations and the AdvancedCollectionView. The custom panel is being used for 2 reasons - to get the Panel and apply implicit animations to it - and to keep the scrollbar on the rightmost side when HorizontalAlignment is Center.
The CollectionView is binded to an ObservableCollection.
To reproduce the issue - just add a lot of items into the ItemSource and try resizing the GridView at different scroll offsets (check video sample)
.
For your this issue, it may be caused by the ListView and GridView UI virtualization, you can try to use VariableSizedWrapGrid as the GridView's ItemsPanel,
<GridView>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
But it will cost much device memory and performance without virtualization. So you should also take into consideration displaying many images in once.
As for displaying the Item that the User is looking at, since there are many items displayed in the screen, the GridView does not know to track witch one.So also as #Pratyay's suggestion, you need to keep track of the item then make the ScrollView witch is in the GridView to scroll to the item.

WP8: ListBox last row won't remain scrolled into view

When vertically scrolling into view, I can pull the last row into view, but on releasing the drag, the last row springs back (partially) out of view. I think inaccuracy of measure can be attributed to a grid that I'm using as the listbox's header but I'm currently unable to fix this to that they work together correctly.
<Border>
<StackPanel>
<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Auto">
<StackPanel>
<Grid x:Name="_headers"/>
<ListBox x:Name="_dataGrid"/>
</StackPanel>
</ScrollViewer>
</StackPanel>
</Border>
**Update
This example removes the scroll and also suffers from the same truncated row problem as the example above. The header grid row also doesn't scroll horizontally with the listbox rows which is an even bigger problem for my solution.
<Border>
<StackPanel>
<Grid x:Name="_headers"/>
<ListBox x:Name="_dataGrid"/>
</StackPanel>
</Border>
It's because you put ScrollViewer inside StackPanel. StackPanel doesn't limit control's size so the ScrollViewer can grow forever and never scroll properly. Its size must be limited. Grid can do it perfectly (if only the height of the row is set to *, not Auto).
Also, in my opinion you shouldn't put ListBox inside ScrollViewer, because ListBox already has its own scroll feature.
Never ever use a ListBox inside a ScrollViewer, you will run into scrolling conflicts.
As far as I can see, you need to add a header to your list. LongListSeelctor might be the best option, since it has got a Header property (also Footer):
See: http://www.geekchamp.com/articles/the-new-longlistselector-control-in-windows-phone-8-sdk-in-depth

StackPanel is not scrolling

I want to put lots of controls inside a StackPanel and user can scroll up and down. I have a simple StackPanel inside a grid.
<Grid>
<StackPanel>
</StackPanel>
</Grid>
If I'm not wrong, I've seen that StackPanel scrolls, but now it is not working. Does it support scrolling or it is not supported at all? ( I prefer not to put it inside a ScrollViewer). thanks
Nothing really scrolls unless it has a ScrollViewer inside. When you do it like you're doing it now, you'll see only the items that fit on the screen, and others will be 'out of screen borders'.
So I'm afraid you'll have to add a ScrollViewer. It's actually a good thing that StackPanel doesn't scroll by default.

ElementFlow element disables controls

I am using the Fluidkit ElementFlow control that I use to display a UserControl that contains textblock with a ScrollViewer as well as button and when they are displayed in the ElementFlow control, all of the buttons and the ScrollViewer seem to be disabled because I can't scroll the ScrollViewer scrollbar and even a simple action as hovering over a button doesn't do anything to the button.
Below is an example of the TextBlock in a ScrollViewer that does not allow for scrolling when used in the ElementFlow.
How can this be fixed?
<ScrollViewer
Height="1200" Width="800"
MaxHeight="1200" MaxWidth="800"
VerticalScrollBarVisibility="Auto">
<TextBlock
Height="Auto" Width="800"
MaxWidth="800"
FontSize="20"
Text="Super long text"
TextWrapping="Wrap"/>
</ScrollViewer>
Just looking over the source code for the project, it looks like it is creating a 3D mesh, and painting the controls on the mesh. This would prevent all user interaction. I don't think there is an easy way to work around this.
However, since you have the source code, you can do the work yourself to make it happen. You're going to need to modify how the ElementFlow represents its items. Look at the CreateMeshModel function. It is currently creating a mesh and applying a VisualBrush to it. Instead, look at the blog post Interacting with 2D on 3D in WPF to figure out what needs to happen.

dockpanel alternatives

I have read that I can't have my dockpanel scroll so im looking for alternatives
I want to have a lot of slider controls(unknown number) left to right in a panel of some sort that can scroll so I can view all the sliders. I tried with dock panel but of course that didn't work. What can I do to make the dockpanel work or what do I replace dockpanel with(the replacement would need to support children)?
Thanks!
EDIT:
http://i.stack.imgur.com/J5a4u.png
here is the idea but it needs to scroll horizontally
David Brunelle Does work but its not quite what I want. Id like the scroll bar to be on the top of the control and not attached to the bottom of the window.
I'm not sure I understand, but you can use a panel within a ScrollViewer
Something like this :
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Margin="2,2,2,2">
...
</StackPanel>
</ScrollViewer>
This will allow for vertical scrolling. You could do the same for horizontal scrolling. I do not know if this would work with a docking panel, but I know it does with a stack panel.
Hope that helps.
I would use a ListBox as it will handle the scrolling part for you, then you can set the ItemTemplate (if you want) and you can use data binding (using an ObservableCollection or a DataView

Categories