Skip to content

Conversation

@MartinZikmund
Copy link
Member

GitHub Issue: closes #22216

PR Type: 🐞 Bugfix

What is the current behavior? 🤔

  • x:DataType has to be specified, even when static-only types are used

What is the new behavior? 🚀

No longer required

PR Checklist ✅

Please check if your PR fulfills the following requirements:

Other information ℹ️

MartinZikmund and others added 3 commits January 21, 2026 15:03
Static-only x:Bind expressions (like {x:Bind local:StaticClass.StaticMember})
in DataTemplates now work without requiring x:DataType, matching WinAppSdk
behavior. This is because static bindings don't access the DataContext.

Fixes #22216

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add source generator tests and runtime tests to verify that static-only
x:Bind expressions work correctly in DataTemplates without x:DataType.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings January 21, 2026 14:14
@github-actions github-actions bot added area/code-generation Categorizes an issue or PR as relevant to code generation area/automation Categorizes an issue or PR as relevant to project automation labels Jan 21, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds support for static x:Bind expressions in DataTemplate elements without requiring the x:DataType attribute. Previously, any x:Bind expression within a DataTemplate required x:DataType to be specified, even when binding exclusively to static properties or methods that don't need access to the DataContext.

Changes:

  • Modified XAML code generator to detect and handle static-only x:Bind expressions in DataTemplates
  • Added detection logic for both property bindings and event bindings to static members
  • Added comprehensive test coverage including unit tests and source generator tests

Reviewed changes

Copilot reviewed 5 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs Core implementation: Added logic to detect static-only bindings for both events (lines 3604-3613) and properties (lines 4226-4256) when x:DataType is missing, allowing the generator to skip the DataType requirement
src/Uno.UI.Tests/Windows_UI_Xaml_Data/xBindTests/Given_xBind_DataTemplate.cs Added two new unit tests to verify static property binding and static event binding work without x:DataType
src/Uno.UI.Tests/Windows_UI_Xaml_Data/xBindTests/Controls/DataTemplate_StaticOnly_NoDataType.xaml Test XAML demonstrating DataTemplate with static-only x:Bind expressions and no x:DataType attribute
src/Uno.UI.Tests/Windows_UI_Xaml_Data/xBindTests/Controls/DataTemplate_StaticOnly_NoDataType.xaml.cs Code-behind for test page with static helper class containing test properties and methods
src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Given_Binding.cs Added two source generator tests for property and event binding scenarios
src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/Given_Binding/WhStXBiPrInDaTeWiDaTy/* Expected generated code output for static property binding test case
src/SourceGenerators/Uno.UI.SourceGenerators.Tests/XamlCodeGeneratorTests/Out/Given_Binding/WhStXBiEvInDaTeWiDaTy/* Expected generated code output for static event binding test case

Comment on lines +4230 to +4236
// Try parsing without a context type to see if it's a static-only binding
var staticContextFunction = XBindExpressionParser.Rewrite("___tctx", rawFunction, null, _metadataHelper.Compilation.GlobalNamespace, isRValue: true, _xBindCounter, FindType, targetPropertyType: null);

// Check if all properties are static (start with global::) or if there are no instance properties
var hasInstanceProperties = staticContextFunction.Properties.Any(p => !p.StartsWith("global::", StringComparison.Ordinal));

if (!hasInstanceProperties && !string.IsNullOrEmpty(rawFunction))
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

The condition checks for an empty rawFunction after verifying hasInstanceProperties, but an empty rawFunction should be handled before attempting to parse it. This could lead to misleading behavior. Consider checking if rawFunction is null or empty before attempting to parse it with XBindExpressionParser.Rewrite, similar to how it's handled elsewhere in the codebase (e.g., line 4332).

Suggested change
// Try parsing without a context type to see if it's a static-only binding
var staticContextFunction = XBindExpressionParser.Rewrite("___tctx", rawFunction, null, _metadataHelper.Compilation.GlobalNamespace, isRValue: true, _xBindCounter, FindType, targetPropertyType: null);
// Check if all properties are static (start with global::) or if there are no instance properties
var hasInstanceProperties = staticContextFunction.Properties.Any(p => !p.StartsWith("global::", StringComparison.Ordinal));
if (!hasInstanceProperties && !string.IsNullOrEmpty(rawFunction))
// If there's no binding expression, we can't infer a static-only binding; keep the original error behavior
if (string.IsNullOrEmpty(rawFunction))
{
// Has no binding expression but no x:DataType - throw the original error
throw new XamlGenerationException("Unable to find x:DataType in enclosing DataTemplate", bindNode);
}
// Try parsing without a context type to see if it's a static-only binding
var staticContextFunction = XBindExpressionParser.Rewrite("___tctx", rawFunction, null, _metadataHelper.Compilation.GlobalNamespace, isRValue: true, _xBindCounter, FindType, targetPropertyType: null);
// Check if all properties are static (start with global::) or if there are no instance properties
var hasInstanceProperties = staticContextFunction.Properties.Any(p => !p.StartsWith("global::", StringComparison.Ordinal));
if (!hasInstanceProperties)

Copilot uses AI. Check for mistakes.
Comment on lines +3604 to +3605
// Check if this is a static method binding (path starts with a namespace prefix like "local:Type")
// Static bindings don't require x:DataType because they don't access the DataContext
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

The comment incorrectly states this feature is for "static method binding" when it actually handles both static properties and static methods. The comment should be updated to reflect that it handles both property and event bindings to static members.

Suggested change
// Check if this is a static method binding (path starts with a namespace prefix like "local:Type")
// Static bindings don't require x:DataType because they don't access the DataContext
// Check if this is a static member binding (path starts with a namespace prefix like "local:Type")
// Static member bindings (methods, properties, events) don't require x:DataType because they don't access the DataContext

Copilot uses AI. Check for mistakes.
@unodevops
Copy link
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22423/wasm-skia-net9/index.html

@unodevops
Copy link
Contributor

🤖 Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22423/docs/index.html

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

Labels

area/automation Categorizes an issue or PR as relevant to project automation area/code-generation Categorizes an issue or PR as relevant to code generation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Static x:Bind in DataTemplate fails without a DataType

3 participants