Current behavior
An indexer binding path whose key contains a . binds to nothing. Path="[a.b]" is split into two path items, [a and b]. The indexer is then called with the key "a", which returns null, and .b] is looked up on that null, so the bound TextBlock shows an empty string.
The cause is in Uno.UI.DataBinding.BindingPath.Parse (read from Uno.UI 6.7.135, the same code in lib/net10.0 (Skia desktop) and lib/net10.0-android36.0). It walks the path backwards and tracks two flags: one for (...) and one for [...]. The case '.' branch checks only the parenthesis flag:
case '.':
if (!flag) // flag = "inside ( )"; the "inside [ ]" flag (flag2) is not consulted
{
TryPrependItem(path, num2 + 1, num, ...);
num = 0;
continue;
}
break;
So a . inside brackets ends a path item. Read through BindingPath.GetPathItems():
| Path |
Items |
[PROJECT.Project_ID] |
[PROJECT, Project_ID] |
[hub.current] |
[hub, current] |
[PROJECT_ID] |
[PROJECT_ID] (one item, works) |
Expected behavior
The text between [ and ] is the indexer argument, dots included, so [a.b] is one indexer item that calls this["a.b"].
That is the documented property-path syntax ("the value inside the brackets is the indexer argument"). I have not run the same binding on WinUI / Windows App SDK to confirm what it does there.
How to reproduce it (as minimally and precisely as possible)
public sealed class Row
{
private readonly Dictionary<string, string> _cells = new() { ["a.b"] = "dotted", ["ab"] = "plain" };
public string? this[string key] => _cells.TryGetValue(key, out var v) ? v : null;
}
// Page code-behind
var row = new Row();
var dotted = new TextBlock { DataContext = row };
dotted.SetBinding(TextBlock.TextProperty, new Binding { Path = new PropertyPath("[a.b]") });
var plain = new TextBlock { DataContext = row };
plain.SetBinding(TextBlock.TextProperty, new Binding { Path = new PropertyPath("[ab]") });
// plain shows "plain"; dotted shows "" (expected "dotted")
The parse can also be shown without rendering anything. BindingPath is internal, so this uses reflection:
var type = typeof(Microsoft.UI.Xaml.Data.Binding).Assembly.GetType("Uno.UI.DataBinding.BindingPath")!;
var path = (IDisposable)Activator.CreateInstance(type, "[a.b]", null)!;
var items = ((IEnumerable)type.GetMethod("GetPathItems")!.Invoke(path, null)!).Cast<object>()
.Select(i => (string)i.GetType().GetProperty("PropertyName")!.GetValue(i)!);
// items == ["[a", "b]"]; expected ["[a.b]"]
Workaround
Keep . out of indexer keys in binding paths. We substitute another character in the key and map it back inside the indexer.
Works on UWP/WinUI
I don't know (not tested here).
Environment
Nuget Package: Uno.WinUI (Uno.Sdk 6.7.x)
Package Version(s): 6.7.135
Affected platform(s):
IDE: Visual Studio 2026
Anything else we need to know?
In our app this blanked every cell of a WinUI.TableView grid whose TableViewTextColumn.Binding paths are [TABLE.Field]. The rows, row selection and accessible row names all worked, so the grid looked populated but empty.
Current behavior
An indexer binding path whose key contains a
.binds to nothing.Path="[a.b]"is split into two path items,[aandb]. The indexer is then called with the key"a", which returns null, and.b]is looked up on that null, so the boundTextBlockshows an empty string.The cause is in
Uno.UI.DataBinding.BindingPath.Parse(read from Uno.UI 6.7.135, the same code inlib/net10.0(Skia desktop) andlib/net10.0-android36.0). It walks the path backwards and tracks two flags: one for(...)and one for[...]. Thecase '.'branch checks only the parenthesis flag:So a
.inside brackets ends a path item. Read throughBindingPath.GetPathItems():[PROJECT.Project_ID][PROJECT,Project_ID][hub.current][hub,current][PROJECT_ID][PROJECT_ID](one item, works)Expected behavior
The text between
[and]is the indexer argument, dots included, so[a.b]is one indexer item that callsthis["a.b"].That is the documented property-path syntax ("the value inside the brackets is the indexer argument"). I have not run the same binding on WinUI / Windows App SDK to confirm what it does there.
How to reproduce it (as minimally and precisely as possible)
The parse can also be shown without rendering anything.
BindingPathis internal, so this uses reflection:Workaround
Keep
.out of indexer keys in binding paths. We substitute another character in the key and map it back inside the indexer.Works on UWP/WinUI
I don't know (not tested here).
Environment
Nuget Package: Uno.WinUI (Uno.Sdk 6.7.x)
Package Version(s): 6.7.135
Affected platform(s):
lib/net10.0code)IDE: Visual Studio 2026
Anything else we need to know?
In our app this blanked every cell of a WinUI.TableView grid whose
TableViewTextColumn.Bindingpaths are[TABLE.Field]. The rows, row selection and accessible row names all worked, so the grid looked populated but empty.