Repository navigation
Conversation
TableView used to derive from ListView, which is where its row virtualization, container generation, row selection storage, and the Windows row visual all came from. That base class had become the limit: hit testing during drag selection scanned every item on every pointer-move frame, row positions were maintained with a visual-tree transform walk per row per scroll frame, cell selection materialised one entry per selected cell, and scroll-into-view was a 10-try realization poll with a magic +8 correction. TableView now derives from Control and hosts its rows in an ItemsRepeater driven by a purpose-built VirtualizingLayout (TableViewRowsLayout). Realized row elements track the viewport height rather than the item count: 200 items and 100,000 items in the same viewport realize the same number of rows. Row selection is a range-based model (TableViewSelectionModel) so selecting a million rows is one range and SelectedItems.Count is O(1). Hit testing, scroll-into-view and PageUp/PageDown are index arithmetic against the layout's row-height store instead of scanning realized containers. Also included, since they follow directly from the base-class change: - TableViewRow is now a ContentControl with its own visual-state machine (the row template is unified across Windows and Uno instead of Windows using the native ListViewItemPresenter). - Automation peers are rewritten on FrameworkElementAutomationPeer with hand-written Selection/Scroll/ItemContainer providers; IGridProvider.GetItem now realizes off-screen rows on demand instead of returning null. - Shift+click range selection, previously delegated to ListViewItem, is implemented directly. - A recycled row with an in-flight cell edit now commits it instead of silently dropping it and leaving IsEditing stuck true. - Row drag-reorder (CanDragItems/CanReorderItems), which came entirely from ListViewBase with no code in this library, is not currently supported. ReorderRowsPage documents the gap; see docs/docs/breaking-changes.md. - Fixed: an empty incrementally-loading source was not always asked for its first page. New sample page: Virtualization (item-count switch, select-all timing, jump-to-row, live realized-row counter demonstrating the constant-row-count property). Docs rewritten to describe the new architecture and the breaking changes (README, overview, performance, accessibility, selection, incremental-loading, migration-wct, and a new breaking-changes.md). Verified: Build+Pack green on all 6 target frameworks (net8/9/10, plain and -windows10.0.19041.0), 361/361 tests pass, WinUI sample builds x64, Uno sample builds net10.0-desktop. Grouping support is a separate follow-up PR stacked on this one.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
TableViewused to derive fromListView, which is where its row virtualization, container generation, row selection storage, and the Windows row visual all came from. That base class had become the limiting factor:TransformToVisualwalk per row, per scroll frame.SelectAllon a large grid allocated millions of structs).ScrollRowIntoViewwas a 10-try realization poll with a magic+ 8correction to work aroundListView's async realization.visual row == item index.TableViewnow derives fromControland hosts its rows in anItemsRepeaterdriven by a purpose-builtVirtualizingLayout(TableViewRowsLayout). Realized row elements track the viewport height, not the item count — 200 items and 100,000 items in the same viewport realize the same number of rows. Row selection is a range-based model (TableViewSelectionModel), so selecting a million rows is one range andSelectedItems.Countis O(1). Hit testing, scroll-into-view, and PageUp/PageDown are index arithmetic against the layout's row-height store instead of scanning realized containers.What's included
TableView : Control(was: ListView),TableViewRow : ContentControl(was: ListViewItem), withTableViewRownow owning its own visual-state machine (CommonStates,DisabledStates,MultiSelectStates, pointer-cancel/capture-lost handling).ListViewItemPresenter).src/Layout/(TableViewRowsLayout,TableViewRowHeights,TableViewRowElementFactory) andsrc/Selection/(TableViewSelectionModel,TableViewSelectedItemsCollection,TableViewCellSlotCollection).FrameworkElementAutomationPeerwith hand-written Selection/Scroll/ItemContainer providers.IGridProvider.GetItemnow realizes off-screen rows on demand instead of returningnull— fixes a real accessibility gap.ListViewItem, is implemented directly.overview.md,performance.md,accessibility.md,selection.md,incremental-loading.md,migration-wct.md, README,docs/index.md) plus a newdocs/docs/breaking-changes.md.Fixed along the way
IsEditingstucktruewith the corner menu permanently disabled; it now commits the edit before the row is released.IGridProvider.GetItemreturningnullfor off-screen rows, making large tables effectively unreadable to assistive technology.Breaking changes
This is a deliberate semver-major change — see
docs/docs/breaking-changes.mdfor the full table. Highlights:CanDragItems/CanReorderItemsrow drag-reorder is not currently supported. It came entirely fromListViewBasewith no code in this library, so it disappeared with the base class rather than being ported.ReorderRowsPagedocuments the gap; reimplementing it is tracked as follow-up work.ItemTemplate,ItemsPanel,ItemContainerStyle,Header/Footer,IsItemClickEnabled, and a handful of other inheritedListViewBase/ItemsControlmembers are gone. Everything this repo's own code, samples, and tests actually use was re-declared onTableViewwith the same name/type.Test plan
msbuild /restore /t:Build,Pack src/WinUI.TableView.csproj— green on all 6 target frameworks (net8/9/10, plain and-windows10.0.19041.0)WinUI.TableView.Tests— 361/361 passnet10.0-desktopStacked PR
Multi-level grouping is a separate follow-up PR stacked on this one.
🤖 Generated with Claude Code