ListView - Scrollbar height keeps changing as I scroll - wpf

I have a ListView which is explicitly populated (no binding) with ListViewItems.
Most of the items need to Visible and others should remain collapsed. All the items are of the same height.
The problem is if I have 100 items and first 60 are visible and the bottom 40 are in collapsed state, the scroll bar's height become something based on the assumption that all the 100 items are in visible state and the scroll bar's height becomes less than what it should be. But when I scroll down to 60, it realizes that the rest 40 are in collapsed state and therefore increases the scroll bar's height to make it appropriate for 60 items in the list view.
I initially thought it may be because of virtualization. But I dod not have any binding of data to the list view. I also tried to set the height of the items to 0 that need to be in collapsed state which did not give me the desired result.
What I need is, if there are 60 items visible and 40 collapsed then the scroll bar's height should be based on only 60 items in the list view and should remain constant.
Is it possible to achieve?

I had exactly the same problem, and the answer can be found here: Listbox scrollbar thumb changes size when content is variable height
Shortly, add ScrollViewer.CanContentScroll="False" on the ListBox and the scrollbar will have constant height regardless on the number of collapsed items.
By the way, I am aware that the question is almost 2 years old, however I'd like to leave it for future reference.

I'm not sure what made you decide it wasn't virtualization, as that is what it must be. Try turning off virtualization:
<ListView VirtualizingStackPanel.IsVirtualizing="False" ...

Related

MFC Combobox: Show scrollbar for combobox when there is x items

I have a combobox, but it only shows scrollbar when there is more than 30 items. It causes the combobox becomes too long - can't blame it, but sometimes, people think it's ugly. So Is there a way to limit the max visible items on combobox - like I have 60 items, and the combo box shows only 10 item at a time, use scrollbar to see more items.
Use CBS_DISABLENOSCROLL to always show the scrollbar.
Define the dropdown Width smaller in you dialog resource.
Or Adjust the height as you want inside the program.
Intercept the CBN_DROPDOWN notification
Calculate the size you want.
Call GetComboBoxInfo to get hwndList
Use SetWindowPos with SWP_NOMOVE and SWP_NOZORDER to change the size
Is there a way to limit the max visible items on combobox
Layout your combobox with the resource editor, and set the cursor to where it is marked in red:
It then immediately changes layout to this:
And this is how you set the height of a combobox list.

How animate insert/delete items in StackPanel

I want to animate insert\delete the item in a StackPanel.
Eg: If new item inserted into collection all other items smoothly free space for new item and vice versa.
Can anyone suggest examples or ideas on this topic?
I would animate the Height of objects
If adding, I would add items with a Height of 0 and animate it full size
If deleting, I would animate the height to 0 and remove the item when the height hits 0
This should work for most single-line items, although if your items contain multiple controls that are designed to stretch and fit whatever space is available to them, you might have to find another solution.

Data Grid View and Vertical scrollbars issue

I realized something annoying when using a data grid view control. When I try to set the cell's height by setting the RowTemplate height property to fit more records on the grid, the vertical scroll bar stops acting nicely and the grid doesnt display all the records (it only shows the records that fit on the available space plus one extra record!) until you resize the columns or something like that! But if I set the AutoSizeRowsMod property to AllCells the grid displays all the records, however the cell's height is now too big for me!
Is there a way to control the cell's height and still show all the records on the DGV? Does it even make sense that it's behaving this way?
Thanks

ScrollViewer's Viewport Height VS Actual Height [duplicate]

This question already has answers here:
WPF DataGrid : CanContentScroll property causing odd behavior
(2 answers)
Closed 9 years ago.
Both are quite general terms but I'm curious to know when these height will be different apart from the case we're using Virtualization?
One more question:
I read on MSDN:
If CanContentScroll is true, the values of the ExtentHeight, ScrollableHeight, ViewportHeight, and VerticalOffset properties are number of items. If CanContentScroll is false, the values of these properties are Device Independent Pixels.
However I'm facing an issue with ViewPort Height: I've 2 listbox in application:
1. Which have Virtualization Enabled and CanContentScroll = True.
2. Which have no virtualization and CanContentScroll = True.
In ListBox 1 while drag-drop Viewport Height comes to 4/5 (Number of elements currently visible). However in ListBox 2 i get Viewport Height equal to Actual Height of Listbox.
Why this difference?
Few more findings:
1. Scrollable Height is number of items not visible in scrollviewer
2. Viewport Height is number of items visible in scrollviewer.
Thus Viewport Height + ScrollableHeight = Extent Height
Can someone please explain what's the difference between two listboxes? I need ViewPort hieght in case of Listbox 1
the ActualHeight is the actual height of the ScrollViewer. The Viewport is what is visible from the ScrollViewers Content. So to answer your question: ViewportHeight differs from ActualHeight if the horizontal Scrollbar is visible by the Height of the Scrollbar.
so, to sum this up:
ActualHeight = ViewportHeight + HorizontalScrollbarHeight
Finally This was the root cause:
Quoting from https://stackoverflow.com/a/3062692/3195477:
You are encountering the differences between physical scrolling and
logical scrolling.
As you have discovered, each has its tradeoffs.
Physical scrolling
Physical scrolling (CanContentScroll=false) just goes by pixels, so:
The viewport always represents exactly the same portion of your scroll
extent, giving you a smooth scrolling experience, and but
The entire contents of the DataGrid must have all templates fully
applied and be measured and arranged to determine the size of the
scrollbar, leading to long delays during loading and high RAM usage,
and It doesn't really scroll items so it doesn't understand
ScrollIntoView very well Logical scrolling
Logical scrolling (CanContentScroll=true) calculates its scroll viewport and extent by items instead of pixels, so:
The viewport may show a different number of items at different times,
meaning the number of items in the viewport as compared to the number
of items in the extent varies, causing the scrollbar length to change,
and
Scrolling moves from one item to the next and never in between,
leading to "jerky" scrolling
but
As long as you're using VirtualizingStackPanel under the hood, it only
needs to apply templates and measure and arrange the items that are
actually visible at the moment, and
ScrollIntoView is much simpler since it just needs to get the right
item index into view
Choosing between them
These are the only two kinds of scrolling provided by WPF. You must
choose between them based on the above tradeoffs. Generally logical
scrolling is best for medium to large datasets, and physical scrolling
is best for small ones.
A trick to speed loading during physical scrolling is to make the
physical scrolling better is to wrap your items in a custom Decorator
that has a fixed size and sets its child's Visibility to Hidden when
it is not visible. This prevents the ApplyTemplate, Measure and
Arrange from occuring on the descendant controls of that item until
you're ready for it to happen.
A trick to make physical scrolling's ScrollIntoView more reliable is
to call it twice: Once immediately and once in a dispatcher callback
of DispatcherPriority.ApplicationIdle.
Making logical scroll scrollbar more stable
If all your items are the same height, the number of items visible in
the viewport at any time will stay the same, causing the scroll thumb
size to stay the same (because the ratio with total number if items
doesn't change).
It is also possible to modify the behavior of the ScrollBar itself so
the thumb is always calculated to be a fixed size. To do this without
any hacky code-behind:
Subclass Track to replace the calculation of Thumb position and size in MeasureOverride with your own
Change the ScrollBar template used for the logical-scrolling ScrollBar to use your subclassed Track instead of the regular
one
Change the ScrollViewer template to explicitly set your custom ScrollBar template on the logical-scrolling ScrollBar
(instead of using the default template)
Change the ListBox template to use explicitly set your custom ScrollViewer template on the ScrollViewer it creates
This means copying a lot of template code fom the built-in WPF
templates, so it is not a very elegant solution. But the alternative
to this is to use hacky code-behind to wait until all the templates
are expanded, then find the ScrollBar and just replace the ScrollBar
template with the one that uses your custom Track. This code saves two
large templates (ListBox, ScrollViewer) at the cost of some very
tricky code.
Using a different Panel would be a much larger amount of work:
VirtualizingStackPanel is the only Panel that virtualizes, and only it
and StackPanel to logical scrolling. Since you are taking advantage of
VirtualizingStackPanel's virtualization abilities you would have to
re-implement all of these plus all IScrollInfo info function plus your
regular Panel functions. I could do something like that but I would
allocate several, perhaps many, days to get it right. I recommend you
not try it.
They can differ from the point of (specified) Height being evaluated to any given time during the (ongoing) rendering process.
From MSDN:
There is a difference between the
properties of Height and Width and
ActualHeight and ActualWidth. For
example, the ActualHeight property is
a calculated value based on other
height inputs and the layout system.
The value is set by the layout system
itself, based on an actual rendering
pass, and may therefore lag slightly
behind the set value of properties,
such as Height, that are the basis of
the input change.
Because ActualHeight
is a calculated value, you should be
aware that there could be multiple or
incremental reported changes to it as
a result of various operations by the
layout system. The layout system may
be calculating required measure space
for child elements, constraints by the
parent element, and so on.

Silverlight datagrid scrollbar size is wrong

I've got a Silverlight user control that contains a datagrid. The datagrid is bound to an ObservableCollection. The user control is displayed in a popup window that I show in response to some event in another control
There are about 80 objects in the collection, and I've set a fixed height of 400 on the datagrid, so only about 20 items can be shown at one time, and the vertical scrollbar should be shown, with a thumb size occupying about 1/4th of the control height.
However, what's actually happening is that the scrollbar occupies almost the whole control height; maybe 95% of it. The datagrid displays the first 20 items. When I click on the scrollbar down arrow, the scrollbar moves down a little to occupy the bottom 95% of the scroll area, and the datagrid displays the last 20 items.
It gets weirder. If I move over the items in the grid and scroll down using the mouse wheel, then the items scroll correctly and I can view the whole list, although the scrollbar remains the same size.
And then, if I close the popup and reopen it, the scrollbar now appears with the correct height and it works correctly.
Finally, if I just show the control directly on the page, and not in a popup, it works fine.
What's going on here?! Has anyone else run into this problem? Help!
Update: The problem seems to be the way that I'm showing the popup. For various reasons, I had to implement the popup display in a somewhat tricky way, and it's this that's causing the trouble.
I recoded this, removing some crufty stuff, and the problem went away; see my update. This isn't really a solution as such, but I wanted to close out the question for the record.

Resources