BinaryVirtualizingWrapPanel
A wrap panel for an items control that creates only the items in view: items flow along a line and
wrap onto the next, as in a WrapPanel, but a ListBox of
fifty thousand tiles scrolls as lightly as one of fifty.
public partial class BinaryVirtualizingWrapPanel : VirtualizingPanel, IScrollInfo, ISupportTransactionalUpdates
Inherits from / implements: VirtualizingPanel, IScrollInfo, ISupportTransactionalUpdates
Remarks
Use it as the ItemsPanel of a ListBox – or any items control whose template has a
ScrollViewer with content scrolling on – wherever a long list reads better as tiles than as
rows: photo galleries, product catalogues, file browsers, dashboards of cards.
How it virtualises
The panel is its own scroll owner (IScrollInfo). On
each measure it works out from the offset and the viewport which items are in view, has containers created for
those alone, and keeps or removes the ones that have left the view as VirtualizationSchemeOption
says. Everything else exists only as data, in ItemsControl.ItemsSource.
Two layouts
By default each item gets a cell of ItemDimension, which you must set. A line holds as
many cells as fit (see ItemPositioningMode) and an item's place is arithmetic on its index, so a
jump to any item is cheap. With IsVariableItemSizeEnabled or IsDataSourceGrouped,
a flow layout gives each item its own measured size instead.
Scrolling and grouping
Orientation gives rows that scroll down (the default) or columns that scroll across, a
line – one item – at a time; ScrollToTheDesiredChild takes the user to any item. For groups,
bind the items control to a VirtualizingCollectionView, which presents each group's header as a
row of the flat list, and set IsDataSourceGrouped: the headers are laid out as
GroupVirtualizationMode says and virtualised with the items.
Things to know
- Set the margin through
RendertimeMargin, which the panel copies to itsMarginwhen loaded. - It needs a bounded viewport. Inside a
StackPanel, or any parent that measures with unlimited space along the scrolling direction, there is nothing to virtualise against (seeIsDynamicConstructionCapabilityEnabled). - The items control creates the panel from its
ItemsPanelTemplate: wire its events there and keep a reference from itsLoadedevent (seeScrollToTheDesiredChild).
Examples
A product catalogue as 180 by 140 tiles; Products holds objects with Name and
Price.
<ListBox xmlns:vwp="clr-namespace:Binarymission.WPF.Controls.Panels;assembly=Binarymission.WPF.Controls.VirtualizingWrapPanel"
ItemsSource="{Binding Products}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<vwp:BinaryVirtualizingWrapPanel ItemDimension="180,140" ItemPositioningMode="Safe" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="8">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" TextTrimming="CharacterEllipsis" />
<TextBlock Text="{Binding Price, StringFormat=C}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>See also
Members at a glance
| Constructors | |
|---|---|
BinaryVirtualizingWrapPanel | Creates a panel that lays items out in rows and keeps every container it creates. |
| Properties | |
AutoUpdateViewportOnDetectingTransactionalUpdatesToDataSource | Gets or sets whether the panel refreshes the bound collection view whenever items are added, removed, moved or replaced. |
CanHorizontallyScroll | Gets or sets whether the panel may scroll horizontally. |
CanVerticallyScroll | Gets or sets whether the panel may scroll vertically. |
CustomExtraSpacingBetweenGroupHeaderRowAndDataItemRow | Gets or sets the space between a group's header and its first line of items, when it is not a whole item's height. |
CustomExtraSpacingBetweenGroupRenderingCompletionAndGroupHeaderRowRenderingBegins | Gets or sets the height of the blank line between the end of one group and the next group's header,
in StandaloneLine mode. |
DesiredChildIndexScrollingIsDataContextSynchronized | Gets or sets how the panel settles after a jump to
DesiredChildIndexToScrollTo. |
DesiredChildIndexToScrollTo | Gets or sets the index of the item the panel should bring into view – a jump straight to it, however far down the list it is. |
ExtentHeight | Gets the height of all the content, shown or not – what the vertical scroll bar spans. |
ExtentWidth | Gets the width of all the content, shown or not – what the horizontal scroll bar spans. |
GroupHeaderItemCustomHeight | Gets or sets the height of a group header line – the size the header row's data template is drawn at. |
GroupVirtualizationMode | Gets or sets how a grouped source is laid out: each group's header in line with the items, or starting a line of its own, with or without a blank line before it. |
HorizontalOffset | Gets how far the content is scrolled to the right. |
IsAnimationEnabled | Gets or sets whether the panel plays PanelAnimationEffect as it scrolls a page or a
wheel notch, and when it is laid out again. |
IsAnimationEnabledWhenScrollToASpecificChildIndex | Gets or sets whether the panel fades briefly out and in again when it jumps to an item. |
IsDataSourceGrouped | Gets or sets whether the items control's source is a grouped
VirtualizingCollectionView, so that the panel lays out group headers among the items. |
IsDynamicConstructionCapabilityEnabled | Gets or sets whether the panel uses the items control's actual size as its viewport when its parent measures it with unlimited space. |
IsExtraMarginAtStartupRequired | Gets or sets whether the panel adds ten units to every side of
RendertimeMargin. |
IsRenderItemDimensionHeightSpacingBetweenGroupHeaderAndDataItemRowEnabled | Gets or sets whether a whole item's height of space separates a group's header from its first line of items. |
IsTrimExtraLinkbreakForLeadingRowWithOneChildEnabled | Gets or sets whether, when the lines are too short to hold two items, the space under each group
header shrinks from a whole item's height to
CustomExtraSpacingBetweenGroupHeaderRowAndDataItemRow. |
IsVariableItemSizeEnabled | Gets or sets whether items may each be a different size, rather than all sharing the cell of
ItemDimension. |
ItemDimension | Gets or sets the size of the cell each item is laid out in – and, with variable sizes, the size assumed for an item not yet measured. |
ItemPositioningMode | Gets or sets what the fixed-size layout does with space at the end of a line too narrow for a whole item: leave it empty, or fit one more item, slightly clipped. |
Orientation | Gets or sets the direction items run along a line before wrapping onto the next. |
PanelAnimationEffect | Gets or sets the transition played as the panel scrolls, while IsAnimationEnabled is
on. |
ReRenderVisibilityRangeMaxCount | Gets or sets how many items, from the target onward, a jump to an item is meant to prepare. |
RendertimeMargin | Gets or sets the margin the panel gives itself when it is loaded: the space between the edge of the items control and the lines of items. |
ScrollOwner | Gets or sets the scroll viewer that shows the panel's scroll bars and drives its scrolling. |
ShouldAdjustRightHorizontalAlignmentSetupConsideringScrollInfo | Gets or sets whether right alignment
(ShouldRecomputeViewportExtentSpacingUponAlignment) leaves room for a vertical scroll
bar. |
ShouldAutoAdjustParentItemsControlInternalPadding | Gets or sets whether the panel trims the owning items control's padding so that the first line of items sits snugly in its top-left corner. |
ShouldRecomputeViewportExtentSpacingUponAlignment | Gets or sets whether the panel places its lines of items as its
FrameworkElement.HorizontalAlignment says – centred, or against the right – by moving the space
left at the end of each line into its own margin. |
ShouldRenderExtraLineBeforeHeader | Gets or sets whether, with StandaloneLine grouping (see
GroupVirtualizationMode), a blank line comes before each group's header. |
ShouldRenderItemHeightSpacingAfterAGroupHasBeenRendered | Gets or sets whether the blank line before a group header, in StandaloneLine mode, is a whole
item high. |
ShouldShareUnusedSpaceEquallyOnHorizontalAlignment | Gets or sets whether centring, under ShouldRecomputeViewportExtentSpacingUponAlignment,
splits the space left over exactly in half. |
ShouldUseRenderTimeMarginValuesWhenRecomputingViewPortExtentSpacingAdjustment | Gets or sets whether the margin set for
ShouldRecomputeViewportExtentSpacingUponAlignment keeps the top and bottom of
RendertimeMargin. |
VerticalOffset | Gets how far the content is scrolled down. |
ViewportHeight | Gets the height of the part of the content on show. |
ViewportWidth | Gets the width of the part of the content on show. |
VirtualizationSchemeOption | Gets or sets what the panel does with the containers of items scrolled out of view. |
VirtualizationSchemeWhenScrollingToASpecificChildIndex | Gets or sets what the panel does with the containers left out of view by a jump to an item. |
| Methods | |
ArrangeOverride | Places each created item in its cell, or at its place in the flow layout. |
LineDown | Scrolls on by one line: one item's height laid out horizontally, one item's width laid out vertically. |
LineLeft | Scrolls left by one item's width. |
LineRight | Scrolls right by one item's width. |
LineUp | Scrolls back by one line: one item's height laid out horizontally, one item's width laid out vertically. |
MakeVisible | Scrolls the least distance that brings part of an item into the viewport. |
MeasureOverride | Works out which items are in view, creates and measures their containers, and reports the panel's size. |
MouseWheelDown | Scrolls on by one line for a notch of the mouse wheel, as LineDown does. |
MouseWheelLeft | Scrolls left by one item's width – the step for horizontal wheel scrolling – as
LineLeft does. |
MouseWheelRight | Scrolls right by one item's width – the step for horizontal wheel scrolling – as
LineRight does. |
MouseWheelUp | Scrolls back by one line for a notch of the mouse wheel, as LineUp does. |
OnIsItemsHostChanged | Lays the panel out again when it becomes the items control's items host, which on a window's first show happens after its first measure. |
OnItemsChanged | Drops the containers of items removed, moved or replaced, and – with
AutoUpdateViewportOnDetectingTransactionalUpdatesToDataSource – refreshes the view. |
OnKeyDown | Scrolls one line for the arrow keys – Up and Down call LineUp and
LineDown, Left and Right call LineLeft and LineRight –
after the base class has seen the key. |
OnRenderSizeChanged | Lays the items out again for the panel's new size, keeping the item that was first in view (or
DesiredChildIndexToScrollTo, when set) in view. |
PageDown | Scrolls on by one viewport: its height laid out horizontally, its width laid out vertically. |
PageLeft | Scrolls left by the width of the viewport. |
PageRight | Scrolls right by the width of the viewport. |
PageUp | Scrolls back by one viewport: its height laid out horizontally, its width laid out vertically. |
Refresh | Refreshes the items control's collection view and lays the panel out again from the first item – call it after committing edits to the source, so that what is on screen matches the data. |
ScrollToTheDesiredChild | Takes the user straight to an item, however far away it is, choosing for this jump alone whether the panel fades as it lands and what happens to the containers left behind. |
SetHorizontalOffset | Scrolls the content to a horizontal position. |
SetVerticalOffset | Scrolls the content to a vertical position. |
| Events | |
AboutToRenderChildItems | Occurs when the panel is about to create the items for a new stretch of the list, giving the first and last index about to be shown. |
| Fields | |
CustomExtraSpacingBetweenGroupHeaderRowAndDataItemRowProperty | Identifies the CustomExtraSpacingBetweenGroupHeaderRowAndDataItemRow dependency
property. |
CustomExtraSpacingBetweenGroupRenderingCompletionAndGroupHeaderRowRenderingBeginsProperty | Identifies the
CustomExtraSpacingBetweenGroupRenderingCompletionAndGroupHeaderRowRenderingBegins
dependency property. |
DesiredChildIndexScrollingIsDataContextSynchronizedProperty | Identifies the DesiredChildIndexScrollingIsDataContextSynchronized dependency
property. |
DesiredChildIndexToScrollToProperty | Identifies the DesiredChildIndexToScrollTo dependency property. |
GroupHeaderItemCustomHeightProperty | Identifies the GroupHeaderItemCustomHeight dependency property. |
GroupVirtualizationModeProperty | Identifies the GroupVirtualizationMode dependency property. |
IsAnimationEnabledProperty | Identifies the IsAnimationEnabled dependency property. |
IsAnimationEnabledWhenScrollToASpecificChildIndexProperty | Identifies the IsAnimationEnabledWhenScrollToASpecificChildIndex dependency
property. |
IsDataSourceGroupedProperty | Identifies the IsDataSourceGrouped dependency property. |
IsDynamicConstructionCapabilityEnabledProperty | Identifies the IsDynamicConstructionCapabilityEnabled dependency property. |
IsExtraMarginAtStartupRequiredProperty | Identifies the IsExtraMarginAtStartupRequired dependency property. |
IsRenderItemDimensionHeightSpacingBetweenGroupHeaderAndDataItemRowEnabledProperty | Identifies the
IsRenderItemDimensionHeightSpacingBetweenGroupHeaderAndDataItemRowEnabled dependency
property. |
IsTrimExtraLinkbreakForFirstRowEnabledProperty | Identifies the IsTrimExtraLinkbreakForLeadingRowWithOneChildEnabled dependency
property. |
IsVariableItemSizeEnabledProperty | Identifies the IsVariableItemSizeEnabled dependency property. |
ItemDimensionProperty | Identifies the ItemDimension dependency property. |
ItemPositioningModeProperty | Identifies the ItemPositioningMode dependency property. |
OrientationProperty | Identifies the Orientation dependency property. |
PanelAnimationEffectProperty | Identifies the PanelAnimationEffect dependency property. |
ReRenderVisibilityRangeMaxCountProperty | Identifies the ReRenderVisibilityRangeMaxCount dependency property. |
RendertimeMarginProperty | Identifies the RendertimeMargin dependency property. |
ShouldAutoAdjustParentItemsControlInternalPaddingProperty | Identifies the ShouldAutoAdjustParentItemsControlInternalPadding dependency property. |
ShouldRenderExtraLineBeforeHeaderProperty | Identifies the ShouldRenderExtraLineBeforeHeader dependency property. |
ShouldRenderItemHeightSpacingAfterAGroupHasBeenRenderedProperty | Identifies the ShouldRenderItemHeightSpacingAfterAGroupHasBeenRendered dependency
property. |
VirtualizationSchemeOptionProperty | Identifies the VirtualizationSchemeOption dependency property. |
VirtualizationSchemeWhenScrollingToASpecificChildIndexProperty | Identifies the VirtualizationSchemeWhenScrollingToASpecificChildIndex dependency
property. |
Constructors
BinaryVirtualizingWrapPanel
Creates a panel that lays items out in rows and keeps every container it creates.
Remarks
The items control normally creates it from an
ItemsPanelTemplate; set ItemDimension before it is
shown.
Properties
AutoUpdateViewportOnDetectingTransactionalUpdatesToDataSource
Gets or sets whether the panel refreshes the bound collection view whenever items are added, removed, moved or replaced.
- Value
- The default is
false.
Remarks
Each change then does what Refresh does: refreshes the ICollectionView in
ItemsControl.ItemsSource (nothing, when the source is not a collection view), measures again and
scrolls back to the first item. For a list edited in batches, leave it off and call Refresh
after the batch.
CanHorizontallyScroll
Gets or sets whether the panel may scroll horizontally.
- Value
- Written by the
ScrollOwnerfrom its horizontal scroll bar setting;falseuntil it does.
Remarks
While there is a scroll owner and this is false, SetHorizontalOffset
is ignored. With no scroll owner, offsets are always applied.
CanVerticallyScroll
Gets or sets whether the panel may scroll vertically.
- Value
- Written by the
ScrollOwnerfrom its vertical scroll bar setting;falseuntil it does.
Remarks
While there is a scroll owner and this is false, SetVerticalOffset
is ignored. See CanHorizontallyScroll.
CustomExtraSpacingBetweenGroupHeaderRowAndDataItemRow
Gets or sets the space between a group's header and its first line of items, when it is not a whole item's height.
- Value
- In device-independent units (1/96 inch); the default is 8. A negative value counts as 0.
Remarks
Used when IsRenderItemDimensionHeightSpacingBetweenGroupHeaderAndDataItemRowEnabled is
false, or when IsTrimExtraLinkbreakForLeadingRowWithOneChildEnabled
applies.
CustomExtraSpacingBetweenGroupRenderingCompletionAndGroupHeaderRowRenderingBegins
Gets or sets the height of the blank line between the end of one group and the next group's header,
in StandaloneLine mode.
- Value
- In device-independent units (1/96 inch); the default is 48. A negative value counts as 0.
Remarks
Used with GroupVirtualizationMode set to StandaloneLine,
ShouldRenderExtraLineBeforeHeader on and
ShouldRenderItemHeightSpacingAfterAGroupHasBeenRendered off.
A value set while IsDataSourceGrouped is true and
ShouldRenderItemHeightSpacingAfterAGroupHasBeenRendered is false is
held to at most 80 per cent of the height of ItemDimension (or to 2, when that height
is zero or less). Set ItemDimension first.
DesiredChildIndexScrollingIsDataContextSynchronized
Gets or sets how the panel settles after a jump to
DesiredChildIndexToScrollTo.
- Value
- The default is
false.
Remarks
Despite its name, it does not follow the collection view's current item. After a jump the panel steps
one line back, forward and back again so that the lines round the target are created. With this
false, that happens only when no index, or index 0, is asked for; with it
true, whenever the target is more than two lines from the end.
DesiredChildIndexToScrollTo
Gets or sets the index of the item the panel should bring into view – a jump straight to it, however far down the list it is.
- Value
- The zero-based index in the items control's
Items; the default, -1, asks for no particular item.
Exceptions
System.InvalidOperationException- The value is changed while
IsDataSourceGroupedistrue: jumping to an index is not available with a grouped source.
Remarks
Setting an index of zero or more scrolls so that the line holding that item is near the top of
the viewport, creating only the items around it. The value stays set, and the panel keeps that item
in view when its size changes. While it is -1, the panel sets it itself after the viewport is
resized, to the item that was first in view, so that the user keeps their place. Setting the value
it already has does nothing – call ScrollToTheDesiredChild to repeat a jump. An index
at or past the end of the list does not move the view to a new place.
Jumping relies on the fixed-size layout, where an item's place follows from its index. With
IsVariableItemSizeEnabled on, the panel cannot work out where the item is and does not
take the user to it.
Example
Keep the panel on the photo the view model has selected:
<vwp:BinaryVirtualizingWrapPanel ItemDimension="160,160"
DesiredChildIndexToScrollTo="{Binding SelectedPhotoIndex}" />See also
ExtentHeight
Gets the height of all the content, shown or not – what the vertical scroll bar spans.
- Value
- In device-independent units (1/96 inch). In the fixed-size layout, laid out horizontally, it
is the number of lines times the height of
ItemDimension.
ExtentWidth
Gets the width of all the content, shown or not – what the horizontal scroll bar spans.
- Value
- In device-independent units (1/96 inch). In the fixed-size layout, laid out horizontally, it is the width of one full line of items.
GroupHeaderItemCustomHeight
Gets or sets the height of a group header line – the size the header row's data template is drawn at.
- Value
- In device-independent units (1/96 inch); the default is 24. A negative value counts as 0.
Remarks
Applies in the LineBreak and StandaloneLine modes, where the header is as wide as the
line; laid out vertically, it is the header's height at the top of its column. In
Continuation mode a header takes one item cell instead.
GroupVirtualizationMode
Gets or sets how a grouped source is laid out: each group's header in line with the items, or starting a line of its own, with or without a blank line before it.
- Value
- The default is
LineBreak.
Remarks
Used while IsDataSourceGrouped is true.
- Continuation — A header takes one item cell, and the groups run on along the same lines.
- LineBreak — A header starts a line of its own, as long as the line and
GroupHeaderItemCustomHeighthigh, and its items start on the next line. 8 units separate a group from the next header. - StandaloneLine — As
LineBreak, with a blank line before each header – seeShouldRenderExtraLineBeforeHeader.
Laid out vertically, a header heads its column instead,
GroupHeaderItemCustomHeight tall. A change lays the panel out again from the first
item.
HorizontalOffset
Gets how far the content is scrolled to the right.
- Value
- In device-independent units (1/96 inch) from the left of the content; 0 at the start.
See also
IsAnimationEnabled
Gets or sets whether the panel plays PanelAnimationEffect as it scrolls a page or a
wheel notch, and when it is laid out again.
- Value
trueto play the effect; the default isfalse.
Remarks
The effect plays on PageUp, PageDown, PageLeft,
PageRight, the mouse-wheel steps, LineLeft and LineRight,
and when the panel is resized or refreshed – not on LineUp or LineDown,
nor while the scroll bar's thumb is dragged.
Example
<vwp:BinaryVirtualizingWrapPanel ItemDimension="180,140"
IsAnimationEnabled="True"
PanelAnimationEffect="BlurToNormal" />See also
IsAnimationEnabledWhenScrollToASpecificChildIndex
Gets or sets whether the panel fades briefly out and in again when it jumps to an item.
- Value
truefor the 300-millisecond fade; the default isfalse.
Remarks
ScrollToTheDesiredChild sets this for its own jump from its argument, and restores
it.
IsDataSourceGrouped
Gets or sets whether the items control's source is a grouped
VirtualizingCollectionView, so that the panel lays out group headers among the items.
- Value
truefor a grouped source; the default isfalse.
Remarks
A VirtualizingCollectionView with group descriptions presents each group's
header as a row of its own, ahead of the group's items, whose data is the
CollectionViewGroup – its Name and ItemCount are
there to bind to. With this set, the panel uses the flow layout, starts each group as
GroupVirtualizationMode says, and virtualises headers and items together. Bind to an
ordinary grouped view instead and WPF generates a group item per group, which this panel cannot
virtualise.
While grouped, VirtualizationSchemeOption is held at
VirtualizationScheme.LightWeightCache, and jumping to an index
(DesiredChildIndexToScrollTo, ScrollToTheDesiredChild) is not available.
A change lays the panel out again from the first item.
Example
A catalogue grouped by category. Two implicit data templates draw the rows: one for the header
rows (a CollectionViewGroup) and one for the products.
<Window x:Class="Catalogue.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Catalogue"
xmlns:vwp="clr-namespace:Binarymission.WPF.Controls.Panels;assembly=Binarymission.WPF.Controls.VirtualizingWrapPanel"
Title="Catalogue" Width="960" Height="640">
<ListBox x:Name="catalogue">
<ListBox.Resources>
<DataTemplate DataType="{x:Type CollectionViewGroup}">
<TextBlock FontSize="16" FontWeight="Bold" VerticalAlignment="Center">
<Run Text="{Binding Name, Mode=OneWay}" />
(<Run Text="{Binding ItemCount, Mode=OneWay}" /> products)
</TextBlock>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Product}">
<StackPanel Margin="8">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" TextTrimming="CharacterEllipsis" />
<TextBlock Text="{Binding Price, StringFormat=C}" />
</StackPanel>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<vwp:BinaryVirtualizingWrapPanel ItemDimension="180,120"
IsDataSourceGrouped="True"
GroupVirtualizationMode="LineBreak"
GroupHeaderItemCustomHeight="32" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Window>using System.ComponentModel;
using System.Windows.Data;
using Binarymission.WPF.Data.DataExtensions;
// products is a List<Product>; Product has Name, Price and Category.
var view = new VirtualizingCollectionView(products);
view.SortDescriptions.Add(new SortDescription(nameof(Product.Category), ListSortDirection.Ascending));
view.GroupDescriptions.Add(new PropertyGroupDescription(nameof(Product.Category)));
catalogue.ItemsSource = view;See also
IsDynamicConstructionCapabilityEnabled
Gets or sets whether the panel uses the items control's actual size as its viewport when its parent measures it with unlimited space.
- Value
trueto fall back on the items control's size; the default isfalse.
Remarks
Measured with infinite width or height – inside a StackPanel, say – the panel has no
viewport to virtualise against. With this on, it uses the items control's ActualWidth and
ActualHeight instead, so give the items control a size of its own.
IsExtraMarginAtStartupRequired
Gets or sets whether the panel adds ten units to every side of
RendertimeMargin.
- Value
truefor the larger margin; the default isfalse.
Remarks
Applied when the panel is loaded, and at once when this changes, which also scrolls to the first item.
IsRenderItemDimensionHeightSpacingBetweenGroupHeaderAndDataItemRowEnabled
Gets or sets whether a whole item's height of space separates a group's header from its first line of items.
- Value
true, the default, for one item's height (its width, laid out vertically);falseforCustomExtraSpacingBetweenGroupHeaderRowAndDataItemRow.
Remarks
Applies in the LineBreak and StandaloneLine modes. When the lines are too short for
two items and IsTrimExtraLinkbreakForLeadingRowWithOneChildEnabled is set, the smaller
custom spacing is used even with this on.
IsTrimExtraLinkbreakForLeadingRowWithOneChildEnabled
Gets or sets whether, when the lines are too short to hold two items, the space under each group
header shrinks from a whole item's height to
CustomExtraSpacingBetweenGroupHeaderRowAndDataItemRow.
- Value
true, the default, to shrink it;falseto keep the whole item's height.
Remarks
A narrow panel showing one item per line would otherwise put a large gap under every header. It
matters only while
IsRenderItemDimensionHeightSpacingBetweenGroupHeaderAndDataItemRowEnabled is on.
IsVariableItemSizeEnabled
Gets or sets whether items may each be a different size, rather than all sharing the cell of
ItemDimension.
- Value
false, the default, lays every item out in a cell ofItemDimension;truegives each item the size it asks for.
Remarks
With variable sizes, items flow along each line at their own width (their own height, laid out
vertically) and wrap when the line is full; a line is as tall as its tallest item. An item is
measured when it first comes near the view, and its size is remembered; until then
ItemDimension is its estimate, so set that to a typical item's size and the scroll bar
will be close from the start. Grouping works with variable sizes too.
ItemPositioningMode does not apply, and jumping to an index
(DesiredChildIndexToScrollTo) does not take the user to the item. Turning this on or
off forgets the sizes measured so far.
Example
Notes of different lengths, each as wide as its text needs, up to 320 units:
<ListBox ItemsSource="{Binding Notes}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<vwp:BinaryVirtualizingWrapPanel IsVariableItemSizeEnabled="True" ItemDimension="200,90" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border Padding="10" MaxWidth="320" Background="LightYellow">
<TextBlock Text="{Binding Text}" TextWrapping="Wrap" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>ItemDimension
Gets or sets the size of the cell each item is laid out in – and, with variable sizes, the size assumed for an item not yet measured.
- Value
- Width and height in device-independent units (1/96 inch); the default, infinite both ways, means "not set".
Remarks
In the fixed-size layout every item is measured and arranged in a cell of this size – size it for the
largest item – and the panel knows from an index alone where an item is, which is what lets it virtualise a
huge list without measuring it. Left at the default, the fixed-size layout shows nothing; the flow layout
estimates 100 by 100. A line of scrolling is one cell. A change lays the panel out again from the first item.
In XAML: ItemDimension="200,160".
ItemPositioningMode
Gets or sets what the fixed-size layout does with space at the end of a line too narrow for a whole item: leave it empty, or fit one more item, slightly clipped.
- Value
- The default is
Safe.
Remarks
Safe puts whole items only on a line, so every item seen is complete. Greedy takes one more item when the space left is at least 85 per cent of an item; that last item is clipped by at most fifteen per cent of its width (its height, laid out vertically).
It applies to the fixed-size layout. The flow layout, used with IsVariableItemSizeEnabled
or IsDataSourceGrouped, wraps each item at its own size and does not read it. A change re-counts
the lines and keeps the scroll position.
Orientation
Gets or sets the direction items run along a line before wrapping onto the next.
- Value
Horizontal, the default: rows filled left to right, wrapping downward, scrolled vertically.Vertical: columns filled top to bottom, wrapping to the right, scrolled horizontally.
Remarks
A change scrolls the panel back to the first item.
PanelAnimationEffect
Gets or sets the transition played as the panel scrolls, while IsAnimationEnabled is
on.
- Value
- The default is
AnimationEffect.None.
Remarks
Keep transitions for galleries and showcases: they play on every page and wheel step, and a blur over a large panel costs rendering time on every frame it plays.
ReRenderVisibilityRangeMaxCount
Gets or sets how many items, from the target onward, a jump to an item is meant to prepare.
- Value
- The default is 100; between 15 and 175 is sensible.
Remarks
The items created after a jump are those in view at the new position; this value does not change them.
RendertimeMargin
Gets or sets the margin the panel gives itself when it is loaded: the space between the edge of the items control and the lines of items.
- Value
- In device-independent units (1/96 inch); the default is
10,0,0,10, 10 on the left and bottom.
Remarks
The panel copies this to its own FrameworkElement.Margin when it is loaded and when
IsExtraMarginAtStartupRequired changes.
ScrollOwner
Gets or sets the scroll viewer that shows the panel's scroll bars and drives its scrolling.
- Value
- The
ScrollViewerin the items control's template, set by that scroll viewer when it finds the panel;nulluntil then.
Remarks
Part of IScrollInfo; there is normally no reason to
set it yourself. The scroll viewer must have CanContentScroll on (a ListBox
has) for it to hand scrolling to the panel.
ShouldAdjustRightHorizontalAlignmentSetupConsideringScrollInfo
Gets or sets whether right alignment
(ShouldRecomputeViewportExtentSpacingUponAlignment) leaves room for a vertical scroll
bar.
- Value
true, the default, to addVerticalScrollBarWidthto the left margin;falseto put the lines hard against the right.
ShouldAutoAdjustParentItemsControlInternalPadding
Gets or sets whether the panel trims the owning items control's padding so that the first line of items sits snugly in its top-left corner.
- Value
trueto trim it; the default isfalse.
Remarks
When set, the owner's Padding loses three units on the left and nine at the top – once per
owner, however often the panel is loaded – so the left-most item's border is not cut off and no gap shows
above the first line. Setting it back gives them back. A change scrolls back to the first item.
ShouldRecomputeViewportExtentSpacingUponAlignment
Gets or sets whether the panel places its lines of items as its
FrameworkElement.HorizontalAlignment says – centred, or against the right – by moving the space
left at the end of each line into its own margin.
- Value
trueto align the lines; the default,false, starts them at the left withRendertimeMargin.
Remarks
Only Center and Right are acted on, and only when the viewport is wider than
ExtentWidth. The margin is worked out when this becomes true and each time the
panel is loaded, not as the panel is resized. Setting it back to false restores
RendertimeMargin. See also
ShouldShareUnusedSpaceEquallyOnHorizontalAlignment.
ShouldRenderExtraLineBeforeHeader
Gets or sets whether, with StandaloneLine grouping (see
GroupVirtualizationMode), a blank line comes before each group's header.
- Value
true, the default, for the blank line;falsefor the 8-unit gap ofLineBreak.
Remarks
The blank line is one item high when
ShouldRenderItemHeightSpacingAfterAGroupHasBeenRendered is set, else
CustomExtraSpacingBetweenGroupRenderingCompletionAndGroupHeaderRowRenderingBegins.
ShouldRenderItemHeightSpacingAfterAGroupHasBeenRendered
Gets or sets whether the blank line before a group header, in StandaloneLine mode, is a whole
item high.
- Value
truefor one item's height (its width, laid out vertically); the default,false, usesCustomExtraSpacingBetweenGroupRenderingCompletionAndGroupHeaderRowRenderingBegins.
Remarks
Applies only with GroupVirtualizationMode set to StandaloneLine and
ShouldRenderExtraLineBeforeHeader on.
ShouldUseRenderTimeMarginValuesWhenRecomputingViewPortExtentSpacingAdjustment
Gets or sets whether the margin set for
ShouldRecomputeViewportExtentSpacingUponAlignment keeps the top and bottom of
RendertimeMargin.
- Value
trueto keep them; the default,false, makes them zero.
VerticalOffset
Gets how far the content is scrolled down.
- Value
- In device-independent units (1/96 inch) from the top of the content; 0 at the start.
See also
ViewportHeight
Gets the height of the part of the content on show.
- Value
- In device-independent units (1/96 inch): the height the scroll viewer gives the panel.
ViewportWidth
Gets the width of the part of the content on show.
- Value
- In device-independent units (1/96 inch): the width the scroll viewer gives the panel.
VirtualizationSchemeOption
Gets or sets what the panel does with the containers of items scrolled out of view.
- Value
- The default is
VirtualizationScheme.LightWeightCache.
Remarks
While IsDataSourceGrouped is true, any other value is set back to
VirtualizationScheme.LightWeightCache at once. A jump to an item uses
VirtualizationSchemeWhenScrollingToASpecificChildIndex instead. A change scrolls to the first
item.
VirtualizationSchemeWhenScrollingToASpecificChildIndex
Gets or sets what the panel does with the containers left out of view by a jump to an item.
- Value
- The default is
VirtualizationScheme.DisposeOnLeavingViewPortBounds.
Remarks
Used for the layout passes of a jump only; ordinary scrolling uses
VirtualizationSchemeOption. ScrollToTheDesiredChild sets it for its own jump and
restores it.
Methods
ArrangeOverride
Places each created item in its cell, or at its place in the flow layout.
Parameters
finalSize- The space the panel has been given.
Returns
finalSize.
LineDown
Scrolls on by one line: one item's height laid out horizontally, one item's width laid out vertically.
Remarks
The Down arrow key and the vertical scroll bar's down arrow call it. It stops at the end of the content.
See also
LineLeft
Scrolls left by one item's width.
Remarks
It moves the view only when the content is wider than the viewport – in practice, with
Orientation set to Vertical. Plays PanelAnimationEffect when
IsAnimationEnabled is on.
LineRight
Scrolls right by one item's width.
Remarks
It moves the view only when the content is wider than the viewport – in practice, with
Orientation set to Vertical. Plays PanelAnimationEffect when
IsAnimationEnabled is on.
LineUp
Scrolls back by one line: one item's height laid out horizontally, one item's width laid out vertically.
Remarks
The Up arrow key and the vertical scroll bar's up arrow call it. It stops at the start of the content.
See also
MakeVisible
Scrolls the least distance that brings part of an item into the viewport.
Parameters
visual- The element to bring into view: an item's container, or something inside one.
rectangle- The part of
visualto show, in its own coordinates.
Returns
rectangle, unchanged.
Remarks
WPF calls this for FrameworkElement.BringIntoView, for keyboard focus moving to an
item, and for ListBox.ScrollIntoView. It works in every layout, because it reads the item's
arranged position. It can only reach an item whose container exists; to reach any item by index, use
ScrollToTheDesiredChild. A visual that is not inside the panel is ignored.
MeasureOverride
Works out which items are in view, creates and measures their containers, and reports the panel's size.
Parameters
availableSize- The space offered, normally the viewport. When it is infinite along an axis, see
IsDynamicConstructionCapabilityEnabled.
Returns
The whole of the space offered (or the items control's size used in its place).
MouseWheelDown
Scrolls on by one line for a notch of the mouse wheel, as LineDown does.
Remarks
Plays PanelAnimationEffect when IsAnimationEnabled is on.
MouseWheelLeft
Scrolls left by one item's width – the step for horizontal wheel scrolling – as
LineLeft does.
MouseWheelRight
Scrolls right by one item's width – the step for horizontal wheel scrolling – as
LineRight does.
MouseWheelUp
Scrolls back by one line for a notch of the mouse wheel, as LineUp does.
Remarks
Plays PanelAnimationEffect when IsAnimationEnabled is on.
OnIsItemsHostChanged
Lays the panel out again when it becomes the items control's items host, which on a window's first show happens after its first measure.
Parameters
oldIsItemsHost- Whether the panel was the items host before.
newIsItemsHost- Whether it is now.
OnItemsChanged
Drops the containers of items removed, moved or replaced, and – with
AutoUpdateViewportOnDetectingTransactionalUpdatesToDataSource – refreshes the view.
Parameters
sender- The items control's generator.
args- What changed, and where.
OnKeyDown
Scrolls one line for the arrow keys – Up and Down call LineUp and
LineDown, Left and Right call LineLeft and LineRight –
after the base class has seen the key.
Parameters
e- The key pressed. It is not marked handled, so the items control still sees it.
OnRenderSizeChanged
Lays the items out again for the panel's new size, keeping the item that was first in view (or
DesiredChildIndexToScrollTo, when set) in view.
Parameters
sizeInfo- The old and new size.
PageDown
Scrolls on by one viewport: its height laid out horizontally, its width laid out vertically.
Remarks
Plays PanelAnimationEffect when IsAnimationEnabled is on.
PageLeft
Scrolls left by the width of the viewport.
Remarks
Plays PanelAnimationEffect when IsAnimationEnabled is on.
PageRight
Scrolls right by the width of the viewport.
Remarks
Plays PanelAnimationEffect when IsAnimationEnabled is on.
PageUp
Scrolls back by one viewport: its height laid out horizontally, its width laid out vertically.
Remarks
Plays PanelAnimationEffect when IsAnimationEnabled is on.
Refresh
Refreshes the items control's collection view and lays the panel out again from the first item – call it after committing edits to the source, so that what is on screen matches the data.
Remarks
When the items control's ItemsControl.ItemsSource is an
ICollectionView (a VirtualizingCollectionView or a
ListCollectionView, say), the view is refreshed – re-sorted, re-filtered and regrouped
- the panel is measured again and both offsets go back to 0. With any other source it does
nothing.
This is the panel's implementation of ISupportTransactionalUpdates.Refresh.
AutoUpdateViewportOnDetectingTransactionalUpdatesToDataSource calls it on every change
instead.
Example
// Mark a batch of orders as shipped through the editable view, then bring the tiles up to date.
var view = (IEditableCollectionView)ordersList.ItemsSource;
foreach (Order order in selectedOrders)
{
view.EditItem(order);
order.Status = "Shipped";
view.CommitEdit();
}
panel.Refresh();ScrollToTheDesiredChild
Takes the user straight to an item, however far away it is, choosing for this jump alone whether the panel fades as it lands and what happens to the containers left behind.
Parameters
desiredChildIndexToScrollTo- The zero-based index of the item in the items control's
Items. -1 asks for no particular item; an index at or past the end does not move the view to a new place. performAnimationtrueto fade the panel out and back in (300 milliseconds) as it lands;falseto jump without it.virtualizationScheme- What to do with the containers of the items left out of view by
this jump.
VirtualizationScheme.DisposeOnLeavingViewPortBoundskeeps memory flat after a long jump.
Exceptions
System.InvalidOperationExceptionIsDataSourceGroupedistrue: jumping to an index is not available with a grouped source.
Remarks
The jump is made at once, by setting DesiredChildIndexToScrollTo and laying the panel
out. IsAnimationEnabledWhenScrollToASpecificChildIndex and
VirtualizationSchemeWhenScrollingToASpecificChildIndex are set from the arguments for
the jump and restored afterwards. Unlike setting DesiredChildIndexToScrollTo, calling
this with the same index again jumps again – after the user has scrolled away, say.
Example
An order board: the panel is kept when it loads (it is created by the items control, from the template), and a "Go to order" button takes the clerk to the order typed in.
<ListBox x:Name="ordersList" ItemsSource="{Binding Orders}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<vwp:BinaryVirtualizingWrapPanel ItemDimension="220,110" Loaded="OnPanelLoaded" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>using Binarymission.WPF.Controls.Panels;
private BinaryVirtualizingWrapPanel _panel;
private void OnPanelLoaded(object sender, RoutedEventArgs e)
{
_panel = (BinaryVirtualizingWrapPanel)sender;
}
private void OnGoToOrderClick(object sender, RoutedEventArgs e)
{
int index = _orders.FindIndex(order => order.Number == orderNumberBox.Text);
if (index >= 0 && _panel != null)
{
_panel.ScrollToTheDesiredChild(index, true,
BinaryVirtualizingWrapPanel.VirtualizationScheme.DisposeOnLeavingViewPortBounds);
}
}See also
SetHorizontalOffset
Scrolls the content to a horizontal position.
Parameters
offset- The distance from the left of the content, in device-independent units (1/96
inch). It is held between 0 and
ExtentWidthlessViewportWidth; when the content is no wider than the viewport, it is 0.
Remarks
Ignored while there is a ScrollOwner and CanHorizontallyScroll is
false. The items now in view are created on the next layout pass.
SetVerticalOffset
Scrolls the content to a vertical position.
Parameters
offset- The distance from the top of the content, in device-independent units (1/96
inch). It is held between 0 and
ExtentHeightlessViewportHeight; when the content is no taller than the viewport, it is 0.
Remarks
Ignored while there is a ScrollOwner and CanVerticallyScroll is
false. The items now in view are created on the next layout pass.
Example
// Back to the top of the gallery.
panel.SetVerticalOffset(0);Events
AboutToRenderChildItems
Occurs when the panel is about to create the items for a new stretch of the list, giving the first and last index about to be shown.
Remarks
Raised from the measure pass of the fixed-size layout whenever the first index in view changes – not
during a jump to an item, and not in the flow layout (variable sizes or grouping). Use it to fetch what those
items need, or to show where in the list the user is. Changing ItemDimension from the handler
lays the panel out again from the first item.
See also
Fields
CustomExtraSpacingBetweenGroupHeaderRowAndDataItemRowProperty static
Identifies the CustomExtraSpacingBetweenGroupHeaderRowAndDataItemRow dependency
property.
CustomExtraSpacingBetweenGroupRenderingCompletionAndGroupHeaderRowRenderingBeginsProperty static
Identifies the
CustomExtraSpacingBetweenGroupRenderingCompletionAndGroupHeaderRowRenderingBegins
dependency property.
DesiredChildIndexScrollingIsDataContextSynchronizedProperty static
Identifies the DesiredChildIndexScrollingIsDataContextSynchronized dependency
property.
DesiredChildIndexToScrollToProperty static
Identifies the DesiredChildIndexToScrollTo dependency property.
GroupHeaderItemCustomHeightProperty static
Identifies the GroupHeaderItemCustomHeight dependency property.
GroupVirtualizationModeProperty static
Identifies the GroupVirtualizationMode dependency property.
IsAnimationEnabledProperty static
Identifies the IsAnimationEnabled dependency property.
IsAnimationEnabledWhenScrollToASpecificChildIndexProperty static
Identifies the IsAnimationEnabledWhenScrollToASpecificChildIndex dependency
property.
IsDataSourceGroupedProperty static
Identifies the IsDataSourceGrouped dependency property.
IsDynamicConstructionCapabilityEnabledProperty static
Identifies the IsDynamicConstructionCapabilityEnabled dependency property.
IsExtraMarginAtStartupRequiredProperty static
Identifies the IsExtraMarginAtStartupRequired dependency property.
IsRenderItemDimensionHeightSpacingBetweenGroupHeaderAndDataItemRowEnabledProperty static
Identifies the
IsRenderItemDimensionHeightSpacingBetweenGroupHeaderAndDataItemRowEnabled dependency
property.
IsTrimExtraLinkbreakForFirstRowEnabledProperty static
Identifies the IsTrimExtraLinkbreakForLeadingRowWithOneChildEnabled dependency
property.
IsVariableItemSizeEnabledProperty static
Identifies the IsVariableItemSizeEnabled dependency property.
ItemDimensionProperty static
Identifies the ItemDimension dependency property.
ItemPositioningModeProperty static
Identifies the ItemPositioningMode dependency property.
OrientationProperty static
Identifies the Orientation dependency property.
PanelAnimationEffectProperty static
Identifies the PanelAnimationEffect dependency property.
ReRenderVisibilityRangeMaxCountProperty static
Identifies the ReRenderVisibilityRangeMaxCount dependency property.
RendertimeMarginProperty static
Identifies the RendertimeMargin dependency property.
ShouldAutoAdjustParentItemsControlInternalPaddingProperty static
Identifies the ShouldAutoAdjustParentItemsControlInternalPadding dependency property.
ShouldRenderExtraLineBeforeHeaderProperty static
Identifies the ShouldRenderExtraLineBeforeHeader dependency property.
ShouldRenderItemHeightSpacingAfterAGroupHasBeenRenderedProperty static
Identifies the ShouldRenderItemHeightSpacingAfterAGroupHasBeenRendered dependency
property.
VirtualizationSchemeOptionProperty static
Identifies the VirtualizationSchemeOption dependency property.
VirtualizationSchemeWhenScrollingToASpecificChildIndexProperty static
Identifies the VirtualizationSchemeWhenScrollingToASpecificChildIndex dependency
property.