Table of Contents

Class WrapGrid

Namespace
Icy.UI.Controls
Assembly
IcyUI.dll

An auto-flowing, virtualizing grid of uniformly-sized cells - realized items fill left-to-right and wrap to the next row, e.g. an icon/inventory grid.

public class WrapGrid : SelectingItemsControl, INotifyPropertyChanging, IBindingTarget, INotifyPropertyChanged, INotifyFocusChanged, IContainerLayout, IVirtualizingScrollInfo
Inheritance
WrapGrid
Implements
Inherited Members
Extension Methods

Remarks

Overrides ItemsControl's virtualization geometry (LocateViewportStart()/ RealizeRange(int, float)/ComputeExtentHeight()) with exact row/column arithmetic instead of the base's single-column variable-height estimation - every cell is a fixed, known-upfront ItemWidth×ItemHeight size, so no height cache or anchor-walk is needed. Pooling, CreateContainer(DataTemplate, object) (realizes SelectorItems, inherited via SelectingItemsControl), and ItemsSource's live INotifyCollectionChanged reactivity are all inherited unchanged.

Properties

ItemHeight

Gets or sets the height, in pixels, of every realized cell.

[Range(0, Infinity, MinimumIsExclusive = true)]
public float ItemHeight { get; set; }

Property Value

float

Remarks

Must be greater than 0.

Exceptions

ArgumentOutOfRangeException

value is not greater than zero.

ItemWidth

Gets or sets the width, in pixels, of every realized cell.

[Range(0, Infinity, MinimumIsExclusive = true)]
public float ItemWidth { get; set; }

Property Value

float

Remarks

Must be greater than 0.

Exceptions

ArgumentOutOfRangeException

value is not greater than zero.

Methods

ComputeExtentHeight()

Computes ExtentHeight - the running-average single-column estimate by default. A subclass with different virtualization geometry (e.g. a uniform grid) overrides this with its own formula instead.

protected override float ComputeExtentHeight()

Returns

float

The total height of all items in the collection, estimated via a running average of known heights.

Remarks

Returns 0 before this control's first Arrange(Rectangle) - ContentBounds is still empty then, and reporting Icy.UI.Controls.WrapGrid.ColumnsPerRow's single-column fallback as a real extent would wildly overstate it (e.g. ~5x too tall for a 5-column grid) until the next layout pass corrects it.

GetItemExtent(int)

Gets where the item at index sits in this control's scrollable content - walked from the current viewport anchor through measured heights and the running estimate, the same geometry RealizeRange(int, float) positions containers with. A subclass with different geometry (e.g. a uniform grid) overrides this.

protected override (float Top, float Height) GetItemExtent(int index)

Parameters

index int

The item's index.

Returns

(float Top, float Height)

The item's top offset and its height.

Remarks

Rows are uniform: the item's row times ItemHeight.

LocateViewportStart()

Finds the item whose slot contains the current verticalOffset - via a short walk from the last anchor for a small scroll delta, or a direct estimate for a big jump (spec §5). A subclass with different virtualization geometry overrides this to replace the algorithm entirely.

protected override (int Index, float Offset) LocateViewportStart()

Returns

(int Index, float Offset)

A tuple containing the index of the first item to realize and the pixel offset of its top edge.

RealizeRange(int, float)

Realizes every item whose slot overlaps the viewport (plus a forward-only scroll-ahead buffer), starting the walk at firstIndex/firstOffset; positions each realized container, and de-realizes anything realized but no longer in range. A subclass with different virtualization geometry overrides this to replace the algorithm entirely.

protected override void RealizeRange(int firstIndex, float firstOffset)

Parameters

firstIndex int

The index of the first item to realize in this range walk.

firstOffset float

The pixel offset of the top edge of the first item to realize.

Remarks

firstOffset is intentionally unused - unlike the base's variable-height walk, this fixed-cell layout always re-derives the same value from firstIndex/ ItemHeight/ColumnsPerRow directly (see the per-item row computation below), so passing it through could only ever disagree with that computation, never usefully replace it.

RecordRealizedHeight(int, float)

Folds a freshly measured (EnsureRealized(int)) or finally-measured (Derealize(int)) item's height into the height cache via RecordHeight(int, float) by default. A subclass whose virtualization geometry doesn't depend on measured content height (e.g. a uniform grid, where every cell uses a fixed, known-upfront size) overrides this to no-op - honoring it there would misapply the single-column height-cache's above-viewport anchor correction (see RecordHeight(int, float)) to geometry it has no bearing on.

protected override void RecordRealizedHeight(int index, float height)

Parameters

index int

The item index being realized or de-realized.

height float

The container's just-measured height.

Remarks

No-op: this control's virtualization geometry (ComputeExtentHeight()/ LocateViewportStart()/RealizeRange(int, float)) never consults the base's measured-height cache or its above-viewport anchor correction - every cell uses a fixed, known-upfront ItemWidthxItemHeight size instead. Folding a container's incidental measured content height in here would misapply that correction to unrelated fixed-size geometry, causing spurious scroll-position drift (see VerticalOffsetCorrectionRequested).