-
Notifications
You must be signed in to change notification settings - Fork 837
feat: Support static x:Bind in DataTemplate without x:DataType #22423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
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>
There was a problem hiding this 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 |
| // 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)) |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
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).
| // 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) |
| // 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 |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
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.
| // 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 |
|
🤖 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 |
|
🤖 Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22423/docs/index.html |
GitHub Issue: closes #22216
PR Type: 🐞 Bugfix
What is the current behavior? 🤔
x:DataTypehas to be specified, even when static-only types are usedWhat is the new behavior? 🚀
No longer required
PR Checklist ✅
Please check if your PR fulfills the following requirements:
Screenshots Compare Test Runresults.Other information ℹ️