Current behavior
When a {Binding ElementName=X} is defined in a XAML template and the element named X is created programmatically and added to the visual tree after the template is applied, the binding silently fails. The SourceElement (or whatever target property) remains null.
This is because ApplyElementNameBindings() runs at element load time via BindingHelper.ApplyBindingsOnLoad. At that point, NameScope.FindInNamescopes walks the ancestor chain looking for the name, but the named element doesn't exist yet.
WinUI handles this through deferred name resolution in its binding infrastructure — bindings to not-yet-available element names are resolved when the named element later enters the name scope.
Steps to reproduce
- Create a control template containing
{Binding ElementName=MyElement} targeting some property
- In the control's
OnApplyTemplate, programmatically create a FrameworkElement, set its Name = "MyElement", and add it to the template's visual tree
- The binding never resolves
Expected behavior
The binding should resolve once the named element is added to the visual tree and registered in the name scope, matching WinUI behavior.
Affected scenarios
- DatePickerFlyoutPresenter: creates
DayLoopingSelector, MonthLoopingSelector, YearLoopingSelector programmatically in OnApplyTemplate. The MonochromaticOverlayPresenter elements in the Fluent v2 theme bind to these via ElementName, but the bindings fail. A workaround manually registers names in the NameScope and re-applies bindings.
Root cause
In Uno, setting FrameworkElement.Name does not register the element in any NameScope. The OnNameChanged callback only sets AutomationProperties.AutomationId. There is no mechanism to:
- Register a programmatically-set name in the nearest ancestor
NameScope
- Re-evaluate pending
ElementName bindings when new names are registered
Workaround
Manually find the NameScope, register the name, and call ApplyElementNameBindings() on the consuming elements:
// Find the NameScope
INameScope nameScope = null;
DependencyObject current = someTemplateChild;
while (current is not null)
{
nameScope = NameScope.GetNameScope(current);
if (nameScope is not null) break;
current = (current as FrameworkElement)?.Parent as DependencyObject;
}
// Register the dynamically-created element
nameScope?.RegisterName("MyElement", myElement);
// Re-apply bindings on consumers
if (consumer is IDependencyObjectStoreProvider provider)
{
provider.Store.ApplyElementNameBindings();
}
Environment
- Uno Platform (all targets)
- Affects any
{Binding ElementName=...} where the named element is added programmatically after template application
Current behavior
When a
{Binding ElementName=X}is defined in a XAML template and the element namedXis created programmatically and added to the visual tree after the template is applied, the binding silently fails. TheSourceElement(or whatever target property) remainsnull.This is because
ApplyElementNameBindings()runs at element load time viaBindingHelper.ApplyBindingsOnLoad. At that point,NameScope.FindInNamescopeswalks the ancestor chain looking for the name, but the named element doesn't exist yet.WinUI handles this through deferred name resolution in its binding infrastructure — bindings to not-yet-available element names are resolved when the named element later enters the name scope.
Steps to reproduce
{Binding ElementName=MyElement}targeting some propertyOnApplyTemplate, programmatically create aFrameworkElement, set itsName = "MyElement", and add it to the template's visual treeExpected behavior
The binding should resolve once the named element is added to the visual tree and registered in the name scope, matching WinUI behavior.
Affected scenarios
DayLoopingSelector,MonthLoopingSelector,YearLoopingSelectorprogrammatically inOnApplyTemplate. TheMonochromaticOverlayPresenterelements in the Fluent v2 theme bind to these viaElementName, but the bindings fail. A workaround manually registers names in theNameScopeand re-applies bindings.Root cause
In Uno, setting
FrameworkElement.Namedoes not register the element in anyNameScope. TheOnNameChangedcallback only setsAutomationProperties.AutomationId. There is no mechanism to:NameScopeElementNamebindings when new names are registeredWorkaround
Manually find the
NameScope, register the name, and callApplyElementNameBindings()on the consuming elements:Environment
{Binding ElementName=...}where the named element is added programmatically after template application