diff --git a/.github/workflows/tableview-control.yml b/.github/workflows/tableview-control.yml
new file mode 100644
index 000000000..3d0c255c6
--- /dev/null
+++ b/.github/workflows/tableview-control.yml
@@ -0,0 +1,40 @@
+name: TableView Control Self-Test
+
+# On-demand (NOT part of the every-PR build). Exercises the native C++/WinRT
+# TableView as a first-class Reactor control (Reactor.Controls.TableView, the
+# separate-binary Microsoft.UI.Xaml.Controls.Advanced.dll projected to C#)
+# consumed by Reactor.TestApp's "TableView" tab. The control is gated behind
+# -p:IncludeTableView=true so the shared every-PR CI (which builds Reactor.slnx
+# without the flag) is unaffected; this workflow opts in and asserts the control
+# builds + (best-effort) renders.
+on:
+ workflow_dispatch:
+ pull_request:
+ paths:
+ - "samples/Reactor.TestApp/Demos/TableViewControlDemo.cs"
+ - "samples/Reactor.TestApp/GlobalUsings.TableView.cs"
+ - "samples/Reactor.TestApp/TableViewStrings/**"
+ - "samples/Reactor.TestApp/app.manifest"
+ - "samples/Reactor.TestApp/tableview-control-selftest.ps1"
+ - "samples/Reactor.Controls.TableView/**"
+ - "samples/TableView.Projection/**"
+ - ".github/workflows/tableview-control.yml"
+
+permissions:
+ contents: read
+
+jobs:
+ tableview-control-selftest:
+ name: TableView-in-Reactor control self-test
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
+ with:
+ dotnet-version: 10.0.x
+
+ - name: Build + self-test the TableView control (IncludeTableView=true)
+ shell: pwsh
+ run: ./samples/Reactor.TestApp/tableview-control-selftest.ps1 -Configuration Release -Platform x64
diff --git a/samples/Reactor.Controls.TableView/Factories.cs b/samples/Reactor.Controls.TableView/Factories.cs
new file mode 100644
index 000000000..d7cbb420f
--- /dev/null
+++ b/samples/Reactor.Controls.TableView/Factories.cs
@@ -0,0 +1,50 @@
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.UI.Reactor.Core.V1Protocol;
+using WinUITableView = Microsoft.UI.Xaml.Controls.TableView;
+
+namespace Reactor.Controls;
+
+///
+/// DSL factories for the native TableView Reactor control. Import alongside the
+/// core Reactor factories:
+///
+/// using static Microsoft.UI.Reactor.Factories;
+/// using static Reactor.Controls.Factories;
+///
+///
+///
+/// Registration model — per-library trim unit. The static constructor registers
+/// the with on first
+/// touch of any factory below, so an app that never references this library has
+/// the whole control surface trimmed away. This mirrors the recommended pattern
+/// documented on Microsoft.UI.Reactor.Advanced.Factories.
+///
+public static partial class Factories
+{
+ static Factories()
+ {
+ ControlRegistry.Register(
+ static () => new TableViewHandler());
+ // Register the satellite control's XAML metadata provider so the WinUI XAML loader can
+ // resolve the advanced types when the control's style closure is parsed (code-only host).
+ TableViewStyles.RegisterMetadata();
+ }
+
+ ///
+ /// A native TableView bound to , with columns
+ /// auto-generated from the first item's public properties.
+ ///
+ public static TableViewElement TableView(IEnumerable items, double? height = null) =>
+ new() { Items = items, Height = height };
+
+ ///
+ /// A native TableView bound to with explicit
+ /// .
+ ///
+ public static TableViewElement TableView(
+ IEnumerable items,
+ IReadOnlyList columns,
+ double? height = null) =>
+ new() { Items = items, Columns = columns, Height = height };
+}
diff --git a/samples/Reactor.Controls.TableView/Reactor.Controls.TableView.csproj b/samples/Reactor.Controls.TableView/Reactor.Controls.TableView.csproj
new file mode 100644
index 000000000..1c172d8f0
--- /dev/null
+++ b/samples/Reactor.Controls.TableView/Reactor.Controls.TableView.csproj
@@ -0,0 +1,86 @@
+
+
+
+ net10.0-windows10.0.22621.0
+
+ x64
+ Reactor.Controls
+ Reactor.Controls.TableView
+ disable
+ enable
+ true
+ false
+ false
+
+
+
+
+ true
+ Microsoft.UI.Reactor.TableView
+ 0.0.0-preview
+ Microsoft
+ Microsoft
+ Preview — the native C++/WinRT TableView (separate-binary Microsoft.UI.Xaml.Controls.Tabular.dll, projected vs public WinAppSDK 2.0.1) as a first-class Reactor control.
+ WinUI;WinUI3;WinAppSDK;Reactor;TableView;control
+ https://github.com/microsoft/microsoft-ui-reactor
+ https://github.com/microsoft/microsoft-ui-reactor
+ git
+ $(TargetsForTfmSpecificBuildOutput);_BundleTableViewProjection
+
+ $(NoWarn);NU5100;NU5118;NU5128
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/Reactor.Controls.TableView/Styles/01_TabularSurfaces_themeresources.xaml b/samples/Reactor.Controls.TableView/Styles/01_TabularSurfaces_themeresources.xaml
new file mode 100644
index 000000000..3181f10a1
--- /dev/null
+++ b/samples/Reactor.Controls.TableView/Styles/01_TabularSurfaces_themeresources.xaml
@@ -0,0 +1,306 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0,0,0,1
+ 0,0,1,0
+
+
+ 12,4,12,4
+ 8,4,8,4
+ 28
+ 40
+ 4
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0,0,0,1
+ 0,0,1,0
+
+
+ 12,4,12,4
+ 8,4,8,4
+ 28
+ 40
+ 4
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0,0,0,1
+ 0,0,1,0
+
+
+ 12,4,12,4
+ 8,4,8,4
+ 28
+ 40
+ 4
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/Reactor.Controls.TableView/Styles/02_TableView_themeresources.xaml b/samples/Reactor.Controls.TableView/Styles/02_TableView_themeresources.xaml
new file mode 100644
index 000000000..96edb6fe3
--- /dev/null
+++ b/samples/Reactor.Controls.TableView/Styles/02_TableView_themeresources.xaml
@@ -0,0 +1,300 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 40
+
+
+ 8,4,8,4
+ 0,0,12,0
+ 8
+
+
+ Bold
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 40
+ 8,4,8,4
+ 0,0,12,0
+ 8
+ Bold
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 40
+ 8,4,8,4
+ 0,0,12,0
+ 8
+ Bold
+
+
+
+
+
+
+
+
+
+
+
+
+ 32
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/Reactor.Controls.TableView/Styles/03_SortIndicator_themeresources.xaml b/samples/Reactor.Controls.TableView/Styles/03_SortIndicator_themeresources.xaml
new file mode 100644
index 000000000..86b0867fa
--- /dev/null
+++ b/samples/Reactor.Controls.TableView/Styles/03_SortIndicator_themeresources.xaml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 12
+
+
+ 8
+ 3
+ 2,0,2,0
+
+
diff --git a/samples/Reactor.Controls.TableView/Styles/04_MarqueeSelector_themeresources.xaml b/samples/Reactor.Controls.TableView/Styles/04_MarqueeSelector_themeresources.xaml
new file mode 100644
index 000000000..5ec8ac2e2
--- /dev/null
+++ b/samples/Reactor.Controls.TableView/Styles/04_MarqueeSelector_themeresources.xaml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/Reactor.Controls.TableView/Styles/05_SortIndicator.xaml b/samples/Reactor.Controls.TableView/Styles/05_SortIndicator.xaml
new file mode 100644
index 000000000..90e5d08c8
--- /dev/null
+++ b/samples/Reactor.Controls.TableView/Styles/05_SortIndicator.xaml
@@ -0,0 +1,148 @@
+
+
+
+
+
diff --git a/samples/Reactor.Controls.TableView/Styles/06_EditableContentPresenter.xaml b/samples/Reactor.Controls.TableView/Styles/06_EditableContentPresenter.xaml
new file mode 100644
index 000000000..0dc2b5a41
--- /dev/null
+++ b/samples/Reactor.Controls.TableView/Styles/06_EditableContentPresenter.xaml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
diff --git a/samples/Reactor.Controls.TableView/Styles/07_TableView.xaml b/samples/Reactor.Controls.TableView/Styles/07_TableView.xaml
new file mode 100644
index 000000000..03470787b
--- /dev/null
+++ b/samples/Reactor.Controls.TableView/Styles/07_TableView.xaml
@@ -0,0 +1,449 @@
+
+
+
+
+ 28
+ 8,4,8,4
+ 0,0,12,0
+ 8
+
+
+ 32
+
+
+
+
+
+
+
+
diff --git a/samples/Reactor.Controls.TableView/TableViewCellVisuals.cs b/samples/Reactor.Controls.TableView/TableViewCellVisuals.cs
new file mode 100644
index 000000000..41c92bb2e
--- /dev/null
+++ b/samples/Reactor.Controls.TableView/TableViewCellVisuals.cs
@@ -0,0 +1,168 @@
+using System;
+using System.Globalization;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Data;
+using Microsoft.UI.Xaml.Markup;
+using Microsoft.UI.Xaml.Media;
+using Windows.UI;
+using DataTemplate = Microsoft.UI.Xaml.DataTemplate;
+
+namespace Reactor.Controls;
+
+///
+/// Visual style for a cell. Lets a code-only Reactor consumer render the
+/// native gallery's signature cell visuals — colored Department pills, Status chips, and stoplight
+/// Salary tints — through the first-class TableView(...) control, with no XAML files.
+///
+public enum CellStyle
+{
+ /// Plain text cell (a native TableViewTextColumn).
+ Text,
+ /// A rounded pill with a colored dot + label, tinted by the value (e.g. Department).
+ Pill,
+ /// A rounded chip tinted by a boolean/status value (e.g. Active / Inactive).
+ Chip,
+ /// A full-cell stoplight tint by a numeric value (e.g. Salary), with currency text.
+ Tint,
+}
+
+///
+/// Builds the runtime for a styled column and
+/// registers the shared value-converter. Templates are parsed with (classic
+/// {Binding}, since x:Bind is unavailable in loose XAML); the converter must be in
+/// .Resources before the template loads.
+///
+internal static class TableViewCellTemplates
+{
+ internal const string ConverterKey = "ReactorTableViewCellVisualConverter";
+
+ internal static void EnsureRegistered()
+ {
+ var app = Application.Current;
+ if (app == null)
+ return;
+ var res = app.Resources;
+ // Application.Resources may itself be a XamlControlsResources (Source set), which rejects local
+ // values via the indexer ("Local values are not allowed in resource dictionary with Source set").
+ // Register the converter through a code-created merged dictionary instead (same path the style
+ // closure uses) so {StaticResource} resolves it during XamlReader.Load.
+ if (res.ContainsKey(ConverterKey))
+ return;
+ foreach (var md in res.MergedDictionaries)
+ if (md.ContainsKey(ConverterKey))
+ return;
+ var dict = new ResourceDictionary { [ConverterKey] = new TableViewCellVisualConverter() };
+ res.MergedDictionaries.Add(dict);
+ }
+
+ internal static DataTemplate? Create(string propertyPath, CellStyle style)
+ {
+ EnsureRegistered();
+ var path = XamlEscape(propertyPath);
+ var xaml = style switch
+ {
+ CellStyle.Pill => Pill(path),
+ CellStyle.Chip => Chip(path),
+ CellStyle.Tint => Tint(path),
+ _ => null,
+ };
+ return xaml == null ? null : (DataTemplate)XamlReader.Load(xaml);
+ }
+
+ private const string Ns =
+ "xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"";
+
+ private static string Pill(string p) =>
+ $"" +
+ "" +
+ "" +
+ $"" +
+ $"" +
+ "";
+
+ private static string Chip(string p) =>
+ $"" +
+ "" +
+ $"" +
+ "";
+
+ private static string Tint(string p) =>
+ $"" +
+ "" +
+ $"" +
+ "";
+
+ private static string XamlEscape(string v) =>
+ v.Replace("&", "&", StringComparison.Ordinal)
+ .Replace("\"", """, StringComparison.Ordinal)
+ .Replace("<", "<", StringComparison.Ordinal)
+ .Replace(">", ">", StringComparison.Ordinal);
+}
+
+///
+/// Maps a cell value to the brush/text for a styled cell. Colors mirror the native TableViewSamples
+/// Showcase exactly (Department hues, stoplight Salary tiers, Active/Inactive chip).
+///
+public sealed partial class TableViewCellVisualConverter : IValueConverter
+{
+ public object Convert(object value, Type targetType, object parameter, string language) =>
+ (parameter as string) switch
+ {
+ "PillBg" => Brush(DeptHex(Str(value), translucent: true)),
+ "PillDot" => Brush(DeptHex(Str(value), translucent: false)),
+ "ChipBg" => Brush(IsTrue(value) ? "#5916A34A" : "#5964748B"),
+ "ChipText" => IsTrue(value) ? "Active" : "Inactive",
+ "TintBg" => Brush(SalaryTint(ToDouble(value))),
+ "TintText" => ToDouble(value).ToString("C0", CultureInfo.CurrentCulture),
+ _ => Brush("#00000000"),
+ };
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language) =>
+ throw new NotSupportedException();
+
+ private static string Str(object v) => v?.ToString()?.Trim() ?? "";
+
+ private static bool IsTrue(object v) =>
+ v is bool b ? b : bool.TryParse(Str(v), out var p) && p;
+
+ private static double ToDouble(object v) =>
+ v is IConvertible c ? SafeToDouble(c)
+ : double.TryParse(Str(v), NumberStyles.Any, CultureInfo.CurrentCulture, out var d) ? d : 0;
+
+ private static double SafeToDouble(IConvertible c)
+ {
+ try { return c.ToDouble(CultureInfo.CurrentCulture); } catch { return 0; }
+ }
+
+ // Department hues — exact Showcase map (translucent #4D pill bg, full-opacity #FF dot).
+ private static string DeptHex(string dept, bool translucent)
+ {
+ var a = translucent ? "4D" : "FF";
+ return dept.ToLowerInvariant() switch
+ {
+ "engineering" => "#" + a + "0078D4",
+ "sales" => "#" + a + "14B8A6",
+ "marketing" => "#" + a + "A855F7",
+ "hr" or "human resources" => "#" + a + "F59E0B",
+ "operations" => "#" + a + "EF4444",
+ "design" => "#" + a + "EC4899",
+ "product" => "#" + a + "0EA5E9",
+ "finance" => "#" + a + "22C55E",
+ _ => "#" + a + "64748B",
+ };
+ }
+
+ // Stoplight salary tiers — exact Showcase thresholds.
+ private static string SalaryTint(double salary) =>
+ salary >= 100_000 ? "#4D16A34A" : salary >= 60_000 ? "#4DF59E0B" : "#4DDC2626";
+
+ private static SolidColorBrush Brush(string hex)
+ {
+ hex = hex.TrimStart('#');
+ byte H(int i) => byte.Parse(hex.Substring(i, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+ return new SolidColorBrush(Color.FromArgb(H(0), H(2), H(4), H(6)));
+ }
+}
diff --git a/samples/Reactor.Controls.TableView/TableViewElement.cs b/samples/Reactor.Controls.TableView/TableViewElement.cs
new file mode 100644
index 000000000..b080ffde8
--- /dev/null
+++ b/samples/Reactor.Controls.TableView/TableViewElement.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.UI.Reactor.Core;
+using WinUITableView = Microsoft.UI.Xaml.Controls.TableView;
+using TableViewSelectionMode = Microsoft.UI.Xaml.Controls.TableViewSelectionMode;
+using TableViewSelectionUnit = Microsoft.UI.Xaml.Controls.TableViewSelectionUnit;
+using TableViewGridLinesVisibility = Microsoft.UI.Xaml.Controls.TableViewGridLinesVisibility;
+using TableViewHeadersVisibility = Microsoft.UI.Xaml.Controls.TableViewHeadersVisibility;
+using TableViewSelectionChangedEventArgs = Microsoft.UI.Xaml.Controls.TableViewSelectionChangedEventArgs;
+
+namespace Reactor.Controls;
+
+///
+/// A column definition for : a header, the item property the column
+/// binds to, an optional cell (text / pill / chip / tint), and an optional
+/// pixel width.
+///
+public sealed record TableColumn(string Header, string PropertyPath, CellStyle Style = CellStyle.Text, double Width = double.NaN);
+
+///
+/// First-class Reactor element for the native C++/WinRT
+/// Microsoft.UI.Xaml.Controls.TableView (separate-binary control,
+/// projected vs public WinAppSDK 2.0.1).
+///
+///
+/// Unlike the raw XamlHostElement hatch, this element is reconciled by a
+/// real : typed properties, column definitions,
+/// selection, and reactive ItemsSource updates are diffed and applied as
+/// minimal writes on a single pooled control instance.
+///
+public sealed record TableViewElement : Element
+{
+ /// The data items bound to the table (sets the native control's ItemsSource).
+ public IEnumerable? Items { get; init; }
+
+ ///
+ /// Explicit columns. When null, columns are auto-generated from the
+ /// first item's public properties (convenient for demos; pass explicit
+ /// columns for control over headers/order/binding).
+ ///
+ public IReadOnlyList? Columns { get; init; }
+
+ ///
+ /// Explicit fixed viewport height for the hosted control. When null (the default), the control's
+ /// height is left to layout — i.e. a .Height(...)/.MinHeight(...) modifier or .
+ /// A virtualizing data control needs a bounded viewport to virtualize, so set this (or )
+ /// for large data sets.
+ ///
+ public double? Height { get; init; }
+
+ ///
+ /// When true, the control stretches to fill its layout slot (VerticalAlignment/HorizontalAlignment =
+ /// Stretch + a MinHeight) instead of using a fixed . The gallery pages set this so
+ /// the table fills the available vertical space (matching the reference SamplePresenter's stretched example).
+ ///
+ public bool Stretch { get; init; }
+
+ ///
+ /// Hierarchical (tree-grid) roots. When set, the control binds HierarchicalItemsSource +
+ /// instead of the flat , so the first column
+ /// shows an expand chevron and child rows.
+ ///
+ public System.Collections.IEnumerable? HierarchicalItems { get; init; }
+
+ /// Name of the child-collection property on each hierarchical node (e.g. "Children").
+ public string? HierarchicalChildrenPath { get; init; }
+
+ /// When hierarchical, expand the root nodes (first level) by default after binding.
+ public bool ExpandFirstLevel { get; init; }
+
+ /// Selection mode. When null, the control's default is used.
+ public TableViewSelectionMode? SelectionMode { get; init; }
+
+ /// Selection unit (row / cell / cell-or-row). When null, the control's default is used.
+ public TableViewSelectionUnit? SelectionUnit { get; init; }
+
+ /// Grid-line visibility (none / horizontal / vertical / all).
+ public TableViewGridLinesVisibility? GridLinesVisibility { get; init; }
+
+ /// Header visibility (none / column / row / all).
+ public TableViewHeadersVisibility? HeadersVisibility { get; init; }
+
+ /// Allow the user to sort by clicking column headers.
+ public bool? CanSortColumns { get; init; }
+
+ /// Allow the user to filter columns via the header funnels.
+ public bool? CanFilterColumns { get; init; }
+
+ /// Allow the user to reorder columns by dragging headers.
+ public bool? CanReorderColumns { get; init; }
+
+ /// Allow the user to resize columns by dragging header edges.
+ public bool? CanResizeColumns { get; init; }
+
+ /// Show the leading selection gutter (checkbox column).
+ public bool? IsSelectionGutterVisible { get; init; }
+
+ /// Freeze the first N columns to the leading edge (pinned during horizontal scroll).
+ public int? FrozenColumnCount { get; init; }
+
+ /// One-way selected row index. When null, selection is left to the user.
+ public int? SelectedIndex { get; init; }
+
+ /// Raised when the native control's selection changes (added/removed items).
+ public Action? OnSelectionChanged { get; init; }
+
+ ///
+ /// Invoked once with the live native control after its template is applied (on Loaded). Lets a
+ /// page capture the instance to drive imperative APIs (SortByColumn, SelectAll, AutoSizeColumn,
+ /// scrolling, clipboard) and subscribe to events (Sorted/Filtered/...) for live readouts.
+ ///
+ public Action? OnControlReady { get; init; }
+
+ /// Raw control setters applied after typed properties (escape hatch).
+ public Action[] Setters { get; init; } = Array.Empty>();
+
+ internal TableViewElement() { }
+}
diff --git a/samples/Reactor.Controls.TableView/TableViewHandler.cs b/samples/Reactor.Controls.TableView/TableViewHandler.cs
new file mode 100644
index 000000000..e58744369
--- /dev/null
+++ b/samples/Reactor.Controls.TableView/TableViewHandler.cs
@@ -0,0 +1,411 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.UI.Reactor.Core;
+using Microsoft.UI.Reactor.Core.V1Protocol;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Data;
+using WinUITableView = Microsoft.UI.Xaml.Controls.TableView;
+using TableViewTextColumn = Microsoft.UI.Xaml.Controls.TableViewTextColumn;
+using TableViewTemplateColumn = Microsoft.UI.Xaml.Controls.TableViewTemplateColumn;
+using TableViewColumn = Microsoft.UI.Xaml.Controls.TableViewColumn;
+using TableViewFrozenEdge = Microsoft.UI.Xaml.Controls.TableViewFrozenEdge;
+using GridLength = Microsoft.UI.Xaml.GridLength;
+using TableViewSelectionChangedEventArgs = Microsoft.UI.Xaml.Controls.TableViewSelectionChangedEventArgs;
+using SortDirection = Microsoft.UI.Xaml.Controls.Primitives.SortDirection;
+
+namespace Reactor.Controls;
+
+///
+/// V1 handler that mounts, updates, and unmounts
+/// instances onto the native split-binary .
+/// Mirrors the opt-in control pattern used by Reactor.Advanced's Win2D handlers.
+///
+public sealed class TableViewHandler : IElementHandler
+{
+ /// The most recently mounted native control (used by the demo's headless capture).
+ public static WinUITableView? LastInstance { get; private set; }
+
+ // Per-control sort/filter reshape state. The native TableView owns sort/filter STATE (the column
+ // SortMemberPath/SortDirection/SortIndex + Filter + header chevrons/funnels) and raises Sorted/Filtered;
+ // the CONSUMER owns the DATA -- it must re-order/-filter the items source itself. We honour that
+ // contract by binding an ObservableCollection "view" and rebuilding it from a master snapshot on each
+ // event (matching the reference TableViewSamples SortPage's Sorted/Filtered re-shape model).
+ private sealed class ShapeState
+ {
+ public List