Class WrapGrid
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
Remarks
Must be greater than 0.
Exceptions
- ArgumentOutOfRangeException
valueis 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
Remarks
Must be greater than 0.
Exceptions
- ArgumentOutOfRangeException
valueis 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
indexintThe item's index.
Returns
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
firstIndexintThe index of the first item to realize in this range walk.
firstOffsetfloatThe 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
indexintThe item index being realized or de-realized.
heightfloatThe 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).