Skip to content

refactor: Remove GeneratedBindableCustomProperty from library types - #445

Open
w-ahmad wants to merge 1 commit into
mainfrom
refactor/remove-bindable-custom-property
Open

w-ahmad wants to merge 1 commit into
mainfrom
refactor/remove-bindable-custom-property

Conversation

@w-ahmad

@w-ahmad w-ahmad commented Sep 25, 2026

Copy link
Copy Markdown
Owner

Description

Removes [WinRT.GeneratedBindableCustomProperty] from every class in the TableView library (13 types) and replaces the internal bindings that depended on it. The library now works under Native AOT and JIT without the attribute. Sample and test app models are unchanged.

Why the attribute was needed: under Native AOT, WinUI {Binding} resolves a property by name only if it is a dependency property on a type in the XAML type metadata, or if the type has the attribute. Anything else falls back to ICustomPropertyProvider, which throws NotSupportedException and crashes the app. The library relied on this in three places:

  • TableViewRow, TableViewCell and TableViewRowHeader bound through their plain TableView property ("TableView.RowHeight", "TableView.FontSize", ...).
  • Header content and Date/Time/ComboBox settings bound to column DPs by name. This crashed when columns were created in code rather than declared in app XAML.
  • The default group header template bound {Binding Key} / {Binding Count} to plain properties on TableViewGroupInfo.

Changes:

  • Heights and fonts: row/cell/row header heights and row fonts bind with Source = TableView to TableView DPs.
  • Column header: Content is set directly, and a new Header changed callback keeps it in sync.
  • Date/Time columns: the format is set directly. DateFormat / ClockIdentifier changes reach realized cells via HandleColumnPropertyChanged → row → RefreshElement (new overrides).
  • ComboBox editor: gets ItemsSource, SelectedValuePath, DisplayMemberPath and IsEditable assigned directly, matching the date/time picker editors.
  • Group header: TableViewGroupInfo.Key / Count are now DPs (adds KeyProperty / CountProperty). A new public TableViewGroupHeaderRow.GroupInfo puts TableViewGroupInfo into the library's XAML metadata, so {Binding Key} / {Binding Count} keep working in default and custom group header templates under AOT.
  • Tests: tests that asserted a binding on DateTimeFormatHelper.Format now assert the format value, and new tests cover refreshing it.

Related Issue

Closes #

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 📝 Documentation update
  • ♻️ Refactor
  • 🧪 Test
  • 🔧 Chore / maintenance

Checklist

  • This PR is not from my main branch
  • Tested with WinUI target
  • Tested with Uno Platform target
  • Unit / integration tests added or updated
  • Documentation updated to reflect changes
  • Code follows the project's coding conventions

Screenshots / Recordings

N/A: no visual changes.

Additional Notes

Testing

  • Build: the library builds on all six targets (net8/9/10, Windows and Uno) with no new warnings. The sample app and AotTestApp build.

  • Unit tests: 366/366 pass.

  • Runtime: a probe app, published with Native AOT and also run with JIT, each with columns declared in XAML and created only in code, checked:

    • header content and renames
    • cell/row header height, min and max
    • row font family and size
    • Date/Time format changes
    • ComboBox editor values
    • default and custom ({Binding} and {x:Bind}) group header templates

    All checks pass with no binding errors, except the pre-existing ComboBox issue listed below.

  • Uno: built only, not run. The attributes were Windows-only, and the Uno-side changes are limited to Source = TableView bindings and direct assignments.

Behaviour changes

  • Native AOT apps: app XAML that uses {Binding} to reach plain properties of these library types now crashes. Examples:

    • {Binding TableView.RowHeight, RelativeSource={RelativeSource TemplatedParent}} in a custom cell/row style
    • Column.*, IsCurrent, Cells
    • column DPs through the header's DataContext when the column is created in code

    Use x:Bind, TemplateBinding, or bind to TableView DPs instead. Worth a release-notes entry.

  • Interface removed: the 13 types no longer implement the CsWinRT-generated IBindableCustomPropertyImplementation.

  • ComboBox editor: no longer updates live if the column's properties change mid-edit.

  • Non-AOT apps: no change expected.

  • Docs: unchanged. The guidance that user data models need the attribute still holds.

Known pre-existing AOT issues (unchanged here, tracked separately)

  • Assigning a List<T> / ObservableCollection<T> to the ComboBox editor's ItemsSource throws under AOT; v1.5.0 fails the same way.
  • AutoGenerateColumns produces no columns, and grouping by property name puts every item under a null key under AOT, even with an attributed model.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

A remaining AOT-incompatible row-template binding and duplicate-column header regression must be addressed.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity · 2 Low severity

Open (4)
What changed in this PR

Removes generated bindable-property metadata from library controls and replaces affected bindings for Native AOT compatibility.

Changes:

  • Replaces internal reflective bindings with direct assignments or dependency-property bindings.
  • Adds refresh callbacks for date/time formatting and header changes.
  • Converts group key/count values to dependency properties and updates tests.
File Description
tests/​TableViewTimeColumnTests.cs Tests time formatting and refresh behavior.
tests/​TableViewDateColumnTests.cs Tests date formatting and refresh behavior.
src/​TableViewRowPresenter.cs Binds row-header dimensions directly to TableView.
src/​TableViewRowHeader.cs Removes generated bindable metadata.
src/​TableViewRow.cs Refreshes formatted cells and replaces cell dimension bindings.
src/​TableViewHeaderRow.cs Assigns column-header content directly.
src/​TableViewGroupHeaderRow.cs Exposes group information for XAML metadata.
src/​TableViewCell.cs Removes generated bindable metadata.
src/​TableView.cs Binds row fonts directly to the owning table.
src/​ItemsSource/​TableViewGroupInfo.cs Converts key and count to dependency properties.
src/​Columns/​TableViewToggleSwitchColumn.cs Removes generated bindable metadata.
src/​Columns/​TableViewTimeColumn.cs Directly applies and refreshes clock formatting.
src/​Columns/​TableViewTextColumn.cs Removes generated bindable metadata.
src/​Columns/​TableViewTemplateColumn.cs Removes generated bindable metadata.
src/​Columns/​TableViewNumberColumn.cs Removes generated bindable metadata.
src/​Columns/​TableViewHyperlinkColumn.cs Removes generated bindable metadata.
src/​Columns/​TableViewDateColumn.cs Directly applies and refreshes date formatting.
src/​Columns/​TableViewComboBoxColumn.cs Directly configures generated ComboBox editors.
src/​Columns/​TableViewColumn.cs Synchronizes header content through a callback.
src/​Columns/​TableViewCheckBoxColumn.cs Removes generated bindable metadata.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/TableViewRow.cs
Comment on lines +393 to +394
Path = new PropertyPath(nameof(TableView.RowHeight)),
Source = TableView
Comment on lines +570 to +572
if (d is TableViewColumn column && column.HeaderControl is not null)
{
column.HeaderControl.Content = e.NewValue;
Comment on lines +77 to +78
column.DateFormat = "longdate";
column.RefreshElement(cell, new ColumnTestItem());
Comment on lines +68 to +69
column.ClockIdentifier = "24HourClock";
column.RefreshElement(cell, new ColumnTestItem());

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants