Gallery qualification: DataGridShowCase declares 65 DataGrid instances and 210 column declarations. Column reordering is available on the column header presenters, and the optimized path applies to drag and drop-location indicators clipped by frozen column regions during standard and grouped header reordering.
Operation frequency: column reordering indicator arrange/clip updates can run during pointer move, auto-scroll, horizontal scrolling, resizing, and grid relayout while a column is being dragged. Previously each clipped indicator update allocated a new RectangleGeometry.
Avalonia source basis: Visual.Clip is a styled property registered with AffectsRender, and InvalidateVisual marks the visual dirty (.referenceprojects/Avalonia/src/Avalonia.Base/Visual.cs:52-53,141-149,418-421,446-500). RectangleGeometry.Rect participates in geometry invalidation (.referenceprojects/Avalonia/src/Avalonia.Base/Media/RectangleGeometry.cs:25-33; .referenceprojects/Avalonia/src/Avalonia.Base/Media/Geometry.cs:146-172).
Benefit: repeated clipped column reordering indicator updates now reuse cached RectangleGeometry instances after first use, reducing repeated clip geometry allocation from 1/clipped indicator update to 0 after first while preserving Clip clearing when clipping is no longer needed or an indicator is replaced.
Verification: dotnet build -c Release -f net10.0 tools/performances/AtomUI.Performance/AtomUI.Performance.csproj; dotnet run -c Release -f net10.0 --no-build --project tools/performances/AtomUI.Performance/AtomUI.Performance.csproj -- --verify-datagrid-states; dotnet run -c Release -f net10.0 --no-build --project tools/performances/AtomUI.Performance/AtomUI.Performance.csproj -- --suite datagrid --count 100; git diff --check.
Gallery qualification: DataGridShowCase declares 65 DataGrid instances and 210 column declarations. Grouped header scenarios include DataGridColumnGroupItem leaves, and frozen-column examples use LeftFrozenColumnCount and RightFrozenColumnCount. The optimized path applies to grouped leaf DataGridHeaderViewItem instances that require clipping under frozen columns.
Operation frequency: group column header presenter arrange runs during initial layout, horizontal scrolling, resizing, column width changes, and grid relayout. Previously each clipped grouped leaf header arrange allocated a new RectangleGeometry.
Avalonia source basis: Visual.Clip is a styled property registered with AffectsRender, and InvalidateVisual marks the visual dirty (.referenceprojects/Avalonia/src/Avalonia.Base/Visual.cs:52-53,141-149,418-421,446-500). RectangleGeometry.Rect participates in geometry invalidation (.referenceprojects/Avalonia/src/Avalonia.Base/Media/RectangleGeometry.cs:25-33; .referenceprojects/Avalonia/src/Avalonia.Base/Media/Geometry.cs:146-172).
Benefit: repeated clipped group column header view item arrange now reuses one RectangleGeometry after first use, reducing repeated clip geometry allocation from 1/clipped grouped leaf header arrange to 0 after first while preserving Clip clearing when clipping is no longer needed.
Verification: dotnet build -c Release -f net10.0 tools/performances/AtomUI.Performance/AtomUI.Performance.csproj; dotnet run -c Release -f net10.0 --no-build --project tools/performances/AtomUI.Performance/AtomUI.Performance.csproj -- --verify-datagrid-states; dotnet run -c Release -f net10.0 --no-build --project tools/performances/AtomUI.Performance/AtomUI.Performance.csproj -- --suite datagrid --count 100; git diff --check.
Gallery qualification: DataGridShowCase declares 65 DataGrid instances and 210 column declarations, including multiple frozen-column examples with LeftFrozenColumnCount and RightFrozenColumnCount. The optimized path applies to realized DataGridColumnHeader instances that require clipping under frozen columns or header viewport constraints.
Operation frequency: column header presenter arrange runs during initial layout, horizontal scrolling, resizing, column width changes, and grid relayout. Previously each clipped header arrange allocated a new RectangleGeometry.
Avalonia source basis: Visual.Clip is a styled property registered with AffectsRender, and InvalidateVisual marks the visual dirty (.referenceprojects/Avalonia/src/Avalonia.Base/Visual.cs:52-53,141-149,418-421,446-500). RectangleGeometry.Rect participates in geometry invalidation (.referenceprojects/Avalonia/src/Avalonia.Base/Media/RectangleGeometry.cs:25-33; .referenceprojects/Avalonia/src/Avalonia.Base/Media/Geometry.cs:146-172).
Benefit: repeated clipped column header arrange now reuses one RectangleGeometry after first use, reducing repeated clip geometry allocation from 1/clipped header arrange to 0 after first while preserving Clip clearing when clipping is no longer needed.
Verification: dotnet build -c Release -f net10.0 tools/performances/AtomUI.Performance/AtomUI.Performance.csproj; dotnet run -c Release -f net10.0 --no-build --project tools/performances/AtomUI.Performance/AtomUI.Performance.csproj -- --verify-datagrid-states; dotnet run -c Release -f net10.0 --no-build --project tools/performances/AtomUI.Performance/AtomUI.Performance.csproj -- --suite datagrid --count 100; git diff --check.
Gallery qualification: DataGridShowCase declares 65 DataGrid instances, including multiple frozen-column examples with LeftFrozenColumnCount and RightFrozenColumnCount. The optimized path applies to realized DataGridCell instances that require clipping under frozen columns or horizontal virtualization.
Operation frequency: cells presenter arrange runs during initial layout, horizontal scrolling, resizing, column width changes, grid relayout, and row virtualization reuse. Previously each clipped cell arrange allocated a new RectangleGeometry.
Avalonia source basis: Visual.Clip is a styled property registered with AffectsRender, and InvalidateVisual marks the visual dirty (.referenceprojects/Avalonia/src/Avalonia.Base/Visual.cs:52-53,141-149,418-421,446-500). RectangleGeometry.Rect participates in geometry invalidation (.referenceprojects/Avalonia/src/Avalonia.Base/Media/RectangleGeometry.cs:25-33; .referenceprojects/Avalonia/src/Avalonia.Base/Media/Geometry.cs:146-172).
Benefit: repeated clipped cell arrange now reuses one RectangleGeometry after first use, reducing repeated clip geometry allocation from 1/clipped cell arrange to 0 after first while preserving Clip clearing when clipping is no longer needed.
Verification: dotnet build -c Release -f net10.0 tools/performances/AtomUI.Performance/AtomUI.Performance.csproj; dotnet run -c Release -f net10.0 --no-build --project tools/performances/AtomUI.Performance/AtomUI.Performance.csproj -- --verify-datagrid-states; dotnet run -c Release -f net10.0 --no-build --project tools/performances/AtomUI.Performance/AtomUI.Performance.csproj -- --suite datagrid --count 100; git diff --check.
Gallery qualification: DataGridShowCase declares 65 DataGrid instances; each realized DataGrid creates multiple DataGridRow instances, and every templated row owns one PART_BottomGridLine.
Operation frequency: DataGridRow.ArrangeOverride runs during page navigation layout, resizing, horizontal scrolling, row recycling, and grid relayout; the previous code allocated one RectangleGeometry for the bottom gridline on each realized row arrange.
Avalonia basis: Visual.Clip is a StyledProperty registered with AffectsRender and InvalidateVisual queues the visual for repaint (.referenceprojects/Avalonia/src/Avalonia.Base/Visual.cs:52-53,141-149,418-421). RectangleGeometry.RectProperty is registered with AffectsGeometry, so the reused geometry updates its platform geometry while this change explicitly invalidates the bottom gridline when Rect changes (.referenceprojects/Avalonia/src/Avalonia.Base/Media/RectangleGeometry.cs:25-33; .referenceprojects/Avalonia/src/Avalonia.Base/Media/Geometry.cs:146-172).
Verification: dotnet build -c Release -f net10.0 tools/performances/AtomUI.Performance/AtomUI.Performance.csproj; dotnet run -c Release -f net10.0 --no-build --project tools/performances/AtomUI.Performance/AtomUI.Performance.csproj -- --verify-datagrid-states; dotnet run -c Release -f net10.0 --no-build --project tools/performances/AtomUI.Performance/AtomUI.Performance.csproj -- --suite datagrid --count 100.
Gallery qualification: DataGridShowCase declares 65 DataGrid instances, and each realized DataGrid template owns one DataGridRowsPresenter.
Operation frequency: DataGridRowsPresenter.ArrangeOverride runs during page navigation layout, resizing, and scroll-triggered layout passes; the previous code allocated one RectangleGeometry per arrange.
Avalonia basis: Visual.Clip is a StyledProperty registered with AffectsRender and InvalidateVisual queues the visual for repaint (.referenceprojects/Avalonia/src/Avalonia.Base/Visual.cs:52-53,141-149,418-421). RectangleGeometry.RectProperty is registered with AffectsGeometry, so the reused geometry updates its platform geometry while this change explicitly invalidates the presenter when Rect changes (.referenceprojects/Avalonia/src/Avalonia.Base/Media/RectangleGeometry.cs:25-33; .referenceprojects/Avalonia/src/Avalonia.Base/Media/Geometry.cs:146-172).
Verification: dotnet build -c Release -f net10.0 tools/performances/AtomUI.Performance/AtomUI.Performance.csproj; dotnet run -c Release -f net10.0 --no-build --project tools/performances/AtomUI.Performance/AtomUI.Performance.csproj -- --verify-datagrid-states; dotnet run -c Release -f net10.0 --no-build --project tools/performances/AtomUI.Performance/AtomUI.Performance.csproj -- --suite datagrid --count 100.
Gallery qualification: DataGridShowCase declares 65 DataGrid instances, and each template creates one DataGridRowsPresenter. This removes one constructor-time local ScrollGesture routed subscription per rows presenter. Setup happens whenever a DataGrid template is realized; ScrollGesture runs when users scroll DataGrid rows with touchpad or gesture input.
Behavior: DataGridRowsPresenter now handles ScrollGesture through a class handler and still calls the existing OwningGrid.UpdateScroll(-e.Delta) path. State verification confirms no local ScrollGesture handler remains, the gesture is still marked handled when scrolling occurs, and VerticalOffset still changes.
Documentation: updates the DataGrid performance notes and roadmap, and adds the performance-skill rule that every optimization completion must proactively report benefit in a table with baseline, optimized, formula, improvement, and conclusion.
Avalonia basis: ScrollGestureEvent is a bubble routed event. Event adders call AddHandler and store local routed subscriptions in Interactive._eventHandlers, while AddClassHandler subscribes once through RoutedEvent.Raised and filters by route/type.
Sources: .referenceprojects/Avalonia/src/Avalonia.Base/Input/InputElement.Gestures.cs:65-69; .referenceprojects/Avalonia/src/Avalonia.Base/Input/InputElement.Gestures.cs:197-200; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/Interactive.cs:30-64; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/Interactive.cs:176-190; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/RoutedEvent.cs:78-99.
Gallery qualification: DataGridShowCase declares 65 DataGrid instances, so constructor-time subscriptions are multiplied during page navigation and Gallery setup. This change removes four core input routed subscriptions per grid instance. Setup happens whenever a DataGrid is constructed; KeyDown, KeyUp, GotFocus, and LostFocus run during keyboard navigation and focus movement inside the grid.
Behavior: DataGrid now uses OnKeyDown, OnKeyUp, OnGotFocus, and OnLostFocus overrides to call the existing handler bodies with the same !Handled guard. State verification confirms the grid no longer has local core input handlers, GotFocus still updates ContainsFocus, and Down key navigation still moves the current slot.
Avalonia basis: InputElement registers class handlers that dispatch GotFocus, LostFocus, KeyDown, and KeyUp to the virtual OnGotFocus, OnLostFocus, OnKeyDown, and OnKeyUp methods. Event adders call AddHandler and store per-instance subscriptions in Interactive._eventHandlers; RoutedEvent.AddClassHandler uses RoutedEvent.Raised and route filtering.
Sources: .referenceprojects/Avalonia/src/Avalonia.Base/Input/InputElement.cs:235-240; .referenceprojects/Avalonia/src/Avalonia.Base/Input/InputElement.cs:596-657; .referenceprojects/Avalonia/src/Avalonia.Base/Input/InputElement.cs:106-118; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/Interactive.cs:30-64; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/Interactive.cs:176-190; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/RoutedEvent.cs:78-99.
Gallery qualification: DataGridRowGroupHeader is created per realized row group header in grouped DataGrid views. The DataGrid.RowGroups smoke scenario realizes grouped headers during page setup, and grouped DataGrid pages create these headers during navigation or grouped data display. Setup happens when a new group header instance is created; PointerPressed runs whenever users click a group header to update current slot or toggle grouping behavior.
Correctness: DataGridRowHeader now retries owner-dependent template state from the Owner setter, preventing a null OwningGrid path when a group header template applies the row header before assigning Owner.
Avalonia basis: PointerPressed is a tunnel+bubble routed event. Event adders call AddHandler and store local routed subscriptions in Interactive._eventHandlers, while AddClassHandler subscribes once through RoutedEvent.Raised for the control type. EventRoute still honors handledEventsToo, preserving the original handled-event behavior.
Sources: .referenceprojects/Avalonia/src/Avalonia.Base/Input/InputElement.cs:158-169; .referenceprojects/Avalonia/src/Avalonia.Base/Input/InputElement.cs:380-383; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/Interactive.cs:176-190; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/RoutedEvent.cs:78-99; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/EventRoute.cs:158-170.
Gallery qualification: DataGridRowHeader is the row template header slot created per realized DataGridRow. DataGrid.RowHeaders realizes 8 visible row headers in the performance smoke path, and DataGridShowCase row header, row details, and special-column examples create these headers during page navigation. Setup happens once per realized row during navigation; PointerPressed runs each time a user clicks a row header.
Avalonia basis: PointerPressed is a tunnel+bubble routed event. Event adders call AddHandler and store local routed subscriptions in Interactive._eventHandlers, while AddClassHandler subscribes once through RoutedEvent.Raised for the control type. EventRoute still honors handledEventsToo, so the row header selection path keeps the original handled-event behavior.
Sources: .referenceprojects/Avalonia/src/Avalonia.Base/Input/InputElement.cs:158-169; .referenceprojects/Avalonia/src/Avalonia.Base/Input/InputElement.cs:380-383; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/Interactive.cs:176-190; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/RoutedEvent.cs:78-99; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/EventRoute.cs:158-170.
Gallery qualification: DataGridShowCase has one Grouping table head example with 4 DataGridColumnGroupItem instances. The group headers are realized during DataGrid page navigation, and their header pointer forwarding runs when users press or release grouped headers. Although the instance count is small, this removes the remaining per-header routed subscriptions in the column header cleanup path with no visual or API change.
Avalonia basis: PointerPressed/PointerReleased event adders call AddHandler and store local routed subscriptions in Interactive._eventHandlers, while AddClassHandler subscribes once through RoutedEvent.Raised for the control type.
Sources: .referenceprojects/Avalonia/src/Avalonia.Base/Input/InputElement.cs:380-392; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/Interactive.cs:30-42; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/Interactive.cs:179-190; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/RoutedEvent.cs:78-99.
Gallery qualification: DataGridShowCase declares 65 DataGrid controls and 210 columns; column headers and row expanders are realized during page navigation, header press/release/move runs during resize/reorder/sort, and row details binding runs on row load plus expand/collapse.
Avalonia basis: Pointer event adders call AddHandler and store local subscriptions in Interactive._eventHandlers, while AddClassHandler subscribes once through RoutedEvent.Raised. GetObservable/Bind(IObservable<T>) uses direct observable binding, while BindUtils.RelayBind creates Binding + Source + Path.
Sources: .referenceprojects/Avalonia/src/Avalonia.Base/Input/InputElement.cs:353-389; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/Interactive.cs:176-190; .referenceprojects/Avalonia/src/Avalonia.Base/Interactivity/RoutedEvent.cs:84-99; .referenceprojects/Avalonia/src/Avalonia.Base/AvaloniaObjectExtensions.cs:59-77; src/AtomUI.Core/Data/BindUtils.cs:8-36.