Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e4655bb
docs: add complete how-to documentation for all TableView features
w-ahmad Jun 29, 2026
41510b1
docs: add xref links to API members in all feature docs
w-ahmad Jun 29, 2026
1eaf669
docs: fix invalid api/index.md link in feature-index.md
w-ahmad Jun 29, 2026
b455f8f
docs: apply review feedback across feature documentation
w-ahmad Jun 29, 2026
8076c98
docs: link Key Features table entries to their documentation pages
w-ahmad Jun 29, 2026
9d874f3
docs: xref improvements, corrections, and regenerated API yml
w-ahmad Jun 29, 2026
f10c88c
ci: update ci-docs workflow for PR builds and merged-PR deployment
w-ahmad Jun 29, 2026
e0343a5
remove generated apis
w-ahmad Jun 29, 2026
c657625
Trigger ci-build on all PRs by removing paths-ignore
w-ahmad Jun 29, 2026
26f25e2
docs: document SortMemberPath in sorting.md
w-ahmad Jul 1, 2026
6330c31
docs: add screenshots and apply user review edits
w-ahmad Jul 2, 2026
9a14787
Potential fix for pull request finding
w-ahmad Jul 4, 2026
58d5ac7
Potential fix for pull request finding
w-ahmad Jul 4, 2026
675eadd
Potential fix for pull request finding
w-ahmad Jul 4, 2026
947f916
Potential fix for pull request finding
w-ahmad Jul 4, 2026
0803d3c
Potential fix for pull request finding
w-ahmad Jul 4, 2026
1f86351
Potential fix for pull request finding
w-ahmad Jul 4, 2026
d07e413
Potential fix for pull request finding
w-ahmad Jul 4, 2026
0462ed7
Potential fix for pull request finding
w-ahmad Jul 4, 2026
0c6296a
Potential fix for pull request finding
w-ahmad Jul 4, 2026
0125dce
Potential fix for pull request finding
w-ahmad Jul 4, 2026
a8cb183
Potential fix for pull request finding
w-ahmad Jul 4, 2026
6c05b70
docs: add Native AOT compatibility guide
w-ahmad Jul 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ on:
- 'samples/**'
pull_request:
branches: main
paths-ignore:
- 'docs/**'
- 'samples/**'

jobs:
build:
Expand Down
17 changes: 16 additions & 1 deletion .github/workflows/ci-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ on:
branches: main
paths-ignore:
- 'samples/**'
pull_request:
branches: main
paths-ignore:
- 'samples/**'

jobs:
build:
Expand All @@ -30,11 +34,22 @@ jobs:
- name: Build documentation
run: docfx docs/docfx.json

- uses: actions/upload-pages-artifact@v3
- name: Upload site artifact (PR preview)
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: docs-site
path: artifacts/_site
retention-days: 14

- name: Upload pages artifact (deploy)
if: github.event_name == 'push'
uses: actions/upload-pages-artifact@v3
with:
path: artifacts/_site

publish-docs:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: [build]
environment:
name: github-pages
Expand Down
169 changes: 169 additions & 0 deletions docs/docs/aot-compatibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# Native AOT compatibility

`TableView` relies on runtime bindings and dynamic value resolution for features like sorting, filtering, editing, clipboard, and export. These mechanisms are not fully compatible with IL trimming and Native AOT by default. This page explains what you need to do to make your app work correctly under `<PublishAot>true</PublishAot>`.

> **See also:** [Native AOT deployment overview (.NET)](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/) · [C#/WinRT overview](https://learn.microsoft.com/en-us/windows/apps/develop/platform/csharp-winrt/)

## When this applies

You need to follow this guidance if **any** of the following are true for your project:

- `<PublishAot>true</PublishAot>` is set in your `.csproj`
- `<PublishTrimmed>true</PublishTrimmed>` is set in your `.csproj`
- You see AOT/trimming warnings related to `WinRT` or binding at compile time

## The rule

> Any model class whose **properties are accessed via traditional `{Binding}` expressions** must be marked with `[WinRT.GeneratedBindableCustomProperty]` and declared as `partial`.

Traditional binding (`{Binding PropertyName}`) resolves property values at runtime using the WinRT binding infrastructure. Under Native AOT, that infrastructure requires the `[WinRT.GeneratedBindableCustomProperty]` attribute to generate the necessary binding metadata at compile time. This attribute is part of [C#/WinRT](https://github.com/microsoft/CsWinRT).

## What needs the attribute

### Bound columns (attribute required)

Columns that use a `Binding` property — all built-in bound column types — resolve values at runtime through the WinRT binding system:

```xml
<tv:TableViewTextColumn Header="Name" Binding="{Binding Name}" />
<tv:TableViewNumberColumn Header="Price" Binding="{Binding Price}" />
<tv:TableViewCheckBoxColumn Header="Active" Binding="{Binding IsActive}" />
<tv:TableViewDateColumn Header="Due" Binding="{Binding DueDate}" />
<tv:TableViewTimeColumn Header="Time" Binding="{Binding ActiveAt}" />
<tv:TableViewComboBoxColumn Header="Role" Binding="{Binding Role}" />
<tv:TableViewHyperlinkColumn Header="Url" Binding="{Binding Url}" />
```

Any model class whose properties are accessed by these columns **must** have the attribute.

### Template columns with `{Binding}` (attribute required)

If your `CellTemplate` or `EditingTemplate` uses `{Binding}` to access model properties, the attribute is still required:

```xml
<tv:TableViewTemplateColumn Header="Status">
<tv:TableViewTemplateColumn.CellTemplate>
<DataTemplate>
<!-- {Binding} requires the attribute on the model -->
<TextBlock Text="{Binding StatusLabel}" />
</DataTemplate>
</tv:TableViewTemplateColumn.CellTemplate>
</tv:TableViewTemplateColumn>
```

### Template columns with `{x:Bind}` (attribute NOT required)

When a `TableViewTemplateColumn` uses `{x:Bind}` exclusively in its templates, the binding is compiled at build time and does **not** require the attribute on the model:

```xml
<tv:TableViewTemplateColumn Header="Status">
<tv:TableViewTemplateColumn.CellTemplate>
<DataTemplate x:DataType="local:Product">
<!-- x:Bind generates compile-time code — no attribute needed -->
<TextBlock Text="{x:Bind StatusLabel}" />
</DataTemplate>
</tv:TableViewTemplateColumn.CellTemplate>
</tv:TableViewTemplateColumn>
```

## How to apply the attribute

Add `[WinRT.GeneratedBindableCustomProperty]` to your model class and mark it as `partial`:

```csharp
using WinRT;

[GeneratedBindableCustomProperty]
public partial class Product
{
public string? Name { get; set; }
public double Price { get; set; }
public bool InStock { get; set; }
}
```

> **Important:** The class **must** be `partial`. Without `partial`, the source generator cannot emit the required binding implementation and the build will fail.

## Using CommunityToolkit.Mvvm

If your models use [`ObservableObject`](https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/observableobject) from [CommunityToolkit.Mvvm](https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/), combine both attributes. Use `partial` properties with [`[ObservableProperty]`](https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/generators/observableproperty) as normal:

```csharp
using CommunityToolkit.Mvvm.ComponentModel;
using WinRT;

[GeneratedBindableCustomProperty]
public partial class Product : ObservableObject
{
[ObservableProperty]
public partial string? Name { get; set; }

[ObservableProperty]
public partial double Price { get; set; }

[ObservableProperty]
public partial bool InStock { get; set; }
}
```

## Nested models

If a column binds to a nested property (e.g. `Binding="{Binding Address.City}"`), the **nested type** must also have the attribute:

```csharp
[GeneratedBindableCustomProperty]
public partial class Order
{
[ObservableProperty]
public partial string? OrderNumber { get; set; }

[ObservableProperty]
public partial Address? ShippingAddress { get; set; }
}

[GeneratedBindableCustomProperty] // Required because columns bind into Address properties
public partial class Address
{
[ObservableProperty]
public partial string? City { get; set; }

[ObservableProperty]
public partial string? Country { get; set; }
}
```

## Project configuration

Enable AOT and set the CsWinRT warning level to catch any remaining issues at build time:

```xml
<PropertyGroup>
<PublishAot>true</PublishAot>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CsWinRTAotWarningLevel>2</CsWinRTAotWarningLevel>
</PropertyGroup>

<!-- Trim only for Release builds -->
<PropertyGroup>
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">true</PublishTrimmed>
</PropertyGroup>
```

`CsWinRTAotWarningLevel=2` upgrades [CsWinRT](https://github.com/microsoft/CsWinRT) AOT hints to errors so missing attributes are caught during the build rather than at runtime.

## Notes and limitations

- Only WinUI 3 (Windows) targets support Native AOT. Uno Platform targets have their own AOT characteristics — consult the [Uno Platform documentation](https://platform.uno/docs/articles/uno-development/aot-compilation.html) for those targets.
- `AutoGenerateColumns="True"` uses reflection to discover properties. This works with the attribute in place, but for maximum AOT compatibility prefer explicit columns (`AutoGenerateColumns="False"`).
- `SortMemberPath` uses reflection-based property access when set. Ensure the model has the attribute when using `SortMemberPath`.

## Related articles

- [Binding data](binding-data.md)
- [Defining columns](defining-columns.md)
- [Column types](column-types.md)
- [Performance guidance](performance.md)
- [.NET Native AOT deployment overview](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/)
- [C#/WinRT overview](https://learn.microsoft.com/en-us/windows/apps/develop/platform/csharp-winrt/)
- [CommunityToolkit.Mvvm](https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/)
- [CsWinRT on GitHub](https://github.com/microsoft/CsWinRT)
101 changes: 101 additions & 0 deletions docs/docs/binding-data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Binding data

`TableView` accepts any `IEnumerable` as its items source. For the best experience, use `ObservableCollection<T>` so that item additions and removals are reflected automatically, and implement `INotifyPropertyChanged` on your model so that cell values update when the underlying data changes.

## When to use it

Use data binding when you have a collection of objects whose properties map to table columns. This is the standard pattern for all TableView usage.

## Basic example

```xml
<tv:TableView ItemsSource="{x:Bind Products}" />
```

```csharp
public sealed partial class MainWindow : Window
{
public ObservableCollection<Product> Products { get; } = new();

public MainWindow()
{
InitializeComponent();
Products.Add(new Product { Name = "Widget", Price = 9.99, InStock = true });
Products.Add(new Product { Name = "Gadget", Price = 24.50, InStock = false });
}
}
```

## Model example

For editable cells, implement `INotifyPropertyChanged` so that changes committed in the editing control propagate back to the UI:

```csharp
public class Product : INotifyPropertyChanged
{
private string? _name;
private double _price;
private bool _inStock;

public string? Name
{
get => _name;
set { _name = value; OnPropertyChanged(nameof(Name)); }
}

public double Price
{
get => _price;
set { _price = value; OnPropertyChanged(nameof(Price)); }
}

public bool InStock
{
get => _inStock;
set { _inStock = value; OnPropertyChanged(nameof(InStock)); }
}

public event PropertyChangedEventHandler? PropertyChanged;

private void OnPropertyChanged(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
```

## Common options

| Property | Type | Default | Description |
|---|---|---|---|
| [`ItemsSource`](xref:WinUI.TableView.TableView.ItemsSource) | `object` | `null` | The data collection to display. |
| [`AutoGenerateColumns`](xref:WinUI.TableView.TableView.AutoGenerateColumns) | `bool` | `true` | When `true`, columns are generated automatically from the public properties of the item type. |

## Using CollectionView

`TableView` wraps your source in an internal `AdvancedCollectionView`. You can access it through `TableView.CollectionView` to apply programmatic sort and filter descriptions.

```csharp
// Sort by price descending
tableView.SortDescriptions.Add(new SortDescription("Price", SortDirection.Descending));
```

## Live shaping

The internal collection view supports live shaping. When you update a property on an item, sorting and filtering re-evaluate automatically:

```csharp
tableView.AllowLiveShaping = true;
```

Live shaping has a performance cost on large collections. Disable it if you do not need items to re-sort or re-filter when individual properties change.

## Notes and limitations

- Setting [`ItemsSource`](xref:WinUI.TableView.TableView.ItemsSource) to `null` clears the table.
- If you replace the entire collection (by assigning a new list to [`ItemsSource`](xref:WinUI.TableView.TableView.ItemsSource)) any applied sort or filter descriptions are preserved on the internal view and applied to the new source.
- The internal [`CollectionView`](xref:WinUI.TableView.TableView.CollectionView) is read-only; do not cast and mutate it directly. Use `TableView.SortDescriptions` and `TableView.FilterDescriptions` instead.

## Related articles

- [AutoGenerateColumns and defining columns](defining-columns.md)
- [Sorting](sorting.md)
- [Filtering](filtering.md)
Loading
Loading