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
VirtualResultList.IsFixedSize Property
Gets a value indicating whether the System.Collections.IList has a fixed size.
public bool IsFixedSize { get; }
Implements IsFixedSize
Property Value
VirtualResultList.IsReadOnly Property
Gets a value indicating whether the System.Collections.IList is read-only.
public bool IsReadOnly { get; }
Implements IsReadOnly
Property Value
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
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
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
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
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