FindMyFiles

FindMyFiles.Virtualization

VirtualResultList Class

Random-access data virtualization for ListView: non-generic IList + INotifyCollectionChanged + IItemsRangeInfo (the only combination that works — microsoft-ui-xaml#1809, ADR-0015). The indexer hands out stable placeholder instances and never fetches; RangesChanged drives 64-row page fetches on a background task, and arriving data fills those same instances in place.

The instance lives as long as the page: new query results arrive through Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter) (seeded pages + one Reset), never by swapping the ItemsSource (ADR-0015). An epoch counter makes fetches started against a previous result fall on the floor.

Membership invariant — the WinRT IList adapter trusts these answers blindly: **never vouch for membership falsely.** A false "absent" merely re-realizes a container; a false "present" sends the ListView to GetAt(staleIndex) and dies deep inside XAML (ADR-0015). A row is a member iff its index is inside Count AND the current page cache holds that exact instance in that slot; rows from previous results, evicted pages or transient enumeration answer absent. Mutating entry points enforce the UI thread (always, not just in Debug).

public sealed class VirtualResultList : System.Collections.IList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.Specialized.INotifyCollectionChanged, Microsoft.UI.Xaml.Data.IItemsRangeInfo, System.IDisposable

Inheritance System.Object → VirtualResultList

Implements System.Collections.IList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.Specialized.INotifyCollectionChanged, Microsoft.UI.Xaml.Data.IItemsRangeInfo, System.IDisposable

Constructors

VirtualResultList(IDispatcher) Constructor

Bind the list to dispatcher, the UI-thread gate every mutation is checked against (FindMyFiles.Virtualization.VirtualResultList.EnsureUiThread(System.String)) and the queue background fetch completions marshal back through.

public VirtualResultList(FindMyFiles.Services.IDispatcher dispatcher);

Parameters

dispatcher IDispatcher

The UI-thread dispatcher mutations are gated on and fetch completions are marshaled back through.

Properties

VirtualResultList.Count Property

Row count of the published result, clamped to System.Int32.MaxValue — the fixed size the ListView virtualizes against. Out-of-range indexers throw rather than fetch.

public int Count { get; }

Implements Count

Property Value

System.Int32

VirtualResultList.IsFixedSize Property

Gets a value indicating whether the System.Collections.IList has a fixed size.

public bool IsFixedSize { get; }

Implements IsFixedSize

Property Value

System.Boolean

VirtualResultList.IsReadOnly Property

Gets a value indicating whether the System.Collections.IList is read-only.

public bool IsReadOnly { get; }

Implements IsReadOnly

Property Value

System.Boolean

VirtualResultList.IsSynchronized Property

Gets a value indicating whether access to the System.Collections.ICollection is synchronized (thread safe).

public bool IsSynchronized { get; }

Implements IsSynchronized

Property Value

System.Boolean

VirtualResultList.LastVisibleRange Property

Visible (first, last) indexes from the most recent RangesChanged — what position-preserving requeries prefetch before publishing.

public System.Nullable<(int First,int Last)> LastVisibleRange { get; }

Property Value

System.Nullable<<System.Int32,System.Int32>>

VirtualResultList.SyncRoot Property

Gets an object that can be used to synchronize access to the System.Collections.ICollection.

public object SyncRoot { get; }

Implements SyncRoot

Property Value

System.Object

VirtualResultList.this[int] Property

Hands out the stable ResultRow instance for index (creating the placeholder page on demand) — it never fetches, so realization stays cheap; arriving data fills these same instances in place. The setter is unsupported (read-only list).

public object? this[int index] { get; set; }

Parameters

index System.Int32

Zero-based row index; must be inside Count or it throws (an out-of-range slot is never fabricated into the LRU — ADR-0015).

Implements this[int]

Property Value

System.Object

Exceptions

System.ArgumentOutOfRangeException
index is negative or ≥ Count.

System.NotSupportedException
On set.

Methods

VirtualResultList.Add(object) Method

Adds an item to the System.Collections.IList.

public int Add(object? value);

Parameters

value System.Object

The object to add to the System.Collections.IList.

Implements Add(object)

Returns

System.Int32
The position into which the new element was inserted, or -1 to indicate that the item was not inserted into the collection.

Exceptions

System.NotSupportedException
The System.Collections.IList is read-only.
-or-
The System.Collections.IList has a fixed size.

VirtualResultList.Clear() Method

Removes all items from the System.Collections.IList.

public void Clear();

Implements Clear()

Exceptions

System.NotSupportedException
The System.Collections.IList is read-only.

VirtualResultList.Contains(object) Method

True only for a row whose slot still holds that exact instance. After a Reset the ListView re-locates its selected/focused item through Contains/IndexOf; vouching for a row of a previous result would send XAML to GetAt(staleIndex) and crash (ADR-0015), so membership is never faked.

public bool Contains(object? value);

Parameters

value System.Object

The candidate item to test for membership.

Implements Contains(object)

Returns

System.Boolean
True only when the current cache holds that exact instance in its slot.

VirtualResultList.CopyTo(Array, int) Method

Read surface stays landmine-free: copy what is cached, hand out transient placeholders for the rest (never cached — see GetEnumerator()).

public void CopyTo(System.Array array, int index);

Parameters

array System.Array

Destination array the rows are copied into.

index System.Int32

Start offset in array to copy from.

Implements CopyTo(Array, int)

VirtualResultList.Dispose() Method

Tear the list down at page end: cancel in-flight fetches, dispose the fetch token source, and dispose the owned result. Idempotent in effect — the _disposed guard makes any late fetch continuation bail before it touches the now-freed source.

public void Dispose();

Implements Dispose()

VirtualResultList.GetEnumerator() Method

Enumeration must not disturb the virtualization state: walking a million-row result through the cache would evict every realized viewport page (placeholder flash + refetch). Cached slots yield their live instances; everything else yields transient placeholders, which by the membership invariant safely answer "absent".

public System.Collections.IEnumerator GetEnumerator();

Implements GetEnumerator()

Returns

System.Collections.IEnumerator
An enumerator yielding cached instances and transient placeholders.

VirtualResultList.IndexOf(object) Method

Index of value, or -1, under the same membership invariant as Contains(object): a ResultRow matches only when its Index is inside Count AND the current page cache holds that exact instance in that slot. Rows from previous results or evicted pages answer absent.

public int IndexOf(object? value);

Parameters

value System.Object

The candidate item to locate.

Implements IndexOf(object)

Returns

System.Int32
The row's index, or -1 when it is not a current cached member.

VirtualResultList.Insert(int, object) Method

Inserts an item to the System.Collections.IList at the specified index.

public void Insert(int index, object? value);

Parameters

index System.Int32

The zero-based index at which value should be inserted.

value System.Object

The object to insert into the System.Collections.IList.

Implements Insert(int, object)

Exceptions

System.ArgumentOutOfRangeException
index is not a valid index in the System.Collections.IList.

System.NotSupportedException
The System.Collections.IList is read-only.
-or-
The System.Collections.IList has a fixed size.

System.NullReferenceException
value is null reference in the System.Collections.IList.

VirtualResultList.RangesChanged(ItemIndexRange, IReadOnlyList<ItemIndexRange>) Method

ListView callback whenever the realized viewport moves; records the range and kicks page fetches. Delegates to the WinRT-free FindMyFiles.Virtualization.VirtualResultList.NotifyVisibleRange(System.Int32,System.Int32) seam; trackedItems (the pinned/selected items) is unused — only the visible window drives prefetch.

public void RangesChanged(Microsoft.UI.Xaml.Data.ItemIndexRange visibleRange, System.Collections.Generic.IReadOnlyList<Microsoft.UI.Xaml.Data.ItemIndexRange> trackedItems);

Parameters

visibleRange Microsoft.UI.Xaml.Data.ItemIndexRange

First/last realized item indexes.

trackedItems System.Collections.Generic.IReadOnlyList<Microsoft.UI.Xaml.Data.ItemIndexRange>

Items the host asked to keep tracked; ignored.

Implements RangesChanged(ItemIndexRange, IReadOnlyList<ItemIndexRange>)

VirtualResultList.Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter) Method

Atomically replace the backing result: bump the epoch (in-flight fetches for the old result are cancelled, and their completions drop their data either way), drop the page cache, apply the pre-fetched seeds, then raise one Reset.

Contract: UI thread only (a cross-thread CollectionChanged crashes XAML); seeds must be pages of result within its count; ownership of result transfers to this list (it is disposed by the next Reassign/RefreshInPlace or by Dispose()).

public void Reassign(FindMyFiles.Engine.ISearchResult? result, System.Collections.Generic.IReadOnlyList<FindMyFiles.Virtualization.PageSeed> seeds, FindMyFiles.Highlighting.IHighlighter? highlighter=null);

Parameters

result ISearchResult

The new backing result whose ownership transfers to this list; null clears the list to empty.

seeds System.Collections.Generic.IReadOnlyList<PageSeed>

Pre-fetched pages of result used to fill the viewport before the Reset is raised.

highlighter IHighlighter

Compiled highlighter for the active query; null falls back to Empty.

VirtualResultList.RefreshInPlace(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter) Method

Swap to a result the engine verified to contain the same rows (Unchanged) without raising Reset: realized rows keep their instances and re-fill from the seeds (the MVVM setters only notify on actual value changes, so an idle USN requery repaints nothing). Cached pages are marked unloaded so later scrolling re-fetches from the new handle, and the visible range is re-ensured immediately for pages the seeds missed.

Contract: UI thread only; the engine must have verified result holds the same rows as the published one — same Count required, a mismatch falls back to a full seeded Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter) (Reset) rather than lying about membership; seeds must be pages of result; ownership of result transfers to this list. In-flight fetches of the previous epoch are cancelled here too.

public void RefreshInPlace(FindMyFiles.Engine.ISearchResult result, System.Collections.Generic.IReadOnlyList<FindMyFiles.Virtualization.PageSeed> seeds, FindMyFiles.Highlighting.IHighlighter? highlighter=null);

Parameters

result ISearchResult

The verified-identical result to swap in; ownership transfers to this list. A Count mismatch falls back to Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter).

seeds System.Collections.Generic.IReadOnlyList<PageSeed>

Pre-fetched pages of result that re-fill realized rows in place without a Reset.

highlighter IHighlighter

Compiled highlighter for the active query; null falls back to Empty.

VirtualResultList.Remove(object) Method

Removes the first occurrence of a specific object from the System.Collections.IList.

public void Remove(object? value);

Parameters

value System.Object

The object to remove from the System.Collections.IList.

Implements Remove(object)

Exceptions

System.NotSupportedException
The System.Collections.IList is read-only.
-or-
The System.Collections.IList has a fixed size.

VirtualResultList.RemoveAt(int) Method

Removes the System.Collections.IList item at the specified index.

public void RemoveAt(int index);

Parameters

index System.Int32

The zero-based index of the item to remove.

Implements RemoveAt(int)

Exceptions

System.ArgumentOutOfRangeException
index is not a valid index in the System.Collections.IList.

System.NotSupportedException
The System.Collections.IList is read-only.
-or-
The System.Collections.IList has a fixed size.

Events

VirtualResultList.BecameStale Event

Raised on the UI thread when a fetch reported staleness.

public event Action? BecameStale;

Event Type

System.Action

VirtualResultList.CollectionChanged Event

Raised (Reset) on the UI thread by Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter).

public event NotifyCollectionChangedEventHandler? CollectionChanged;

Implements CollectionChanged

Event Type

System.Collections.Specialized.NotifyCollectionChangedEventHandler