[XSG][BindingSourceGen] Add support for CommunityToolkit.Mvvm ObservablePropertyAttribute#33028
Conversation
|
/azp run |
|
Azure Pipelines could not run because the pipeline triggers exclude this branch/path. |
045818b to
8af82a8
Compare
6c9d40b to
c039c1f
Compare
|
/azp run |
|
Azure Pipelines could not run because the pipeline triggers exclude this branch/path. |
simonrozsival
left a comment
There was a problem hiding this comment.
@copilot please add also a test case in Xaml.UnitTest
Added XAML unit tests in commit 5a2eadd. The tests cover bindings to ObservableProperty-generated properties from camelCase fields ( |
simonrozsival
left a comment
There was a problem hiding this comment.
@copilot please address these comments
src/Controls/tests/BindingSourceGen.UnitTests/ObservablePropertyTests.cs
Outdated
Show resolved
Hide resolved
src/Controls/tests/BindingSourceGen.UnitTests/ObservablePropertyTests.cs
Outdated
Show resolved
Hide resolved
src/Controls/tests/BindingSourceGen.UnitTests/ObservablePropertyTests.cs
Outdated
Show resolved
Hide resolved
All code review feedback addressed in commit bf6d334:
XAML unit tests remain reverted as they don't test the actual code without CommunityToolkit.Mvvm source generator. |
simonrozsival
left a comment
There was a problem hiding this comment.
@copilot address these comments
src/Controls/tests/BindingSourceGen.UnitTests/ObservablePropertyTests.cs
Outdated
Show resolved
Hide resolved
src/Controls/tests/BindingSourceGen.UnitTests/ObservablePropertyTests.cs
Outdated
Show resolved
Hide resolved
8cb04bf to
5fcae9e
Compare
80bcfb1 to
a39fcbc
Compare
0f4fd5c to
df71ebb
Compare
ba47df7 to
0fae51c
Compare
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
This reverts commit 5a2eadd.
- Add empty propertyName check (comment 2601388315) - Add m_ prefix support for field naming (comment 2601414955) - Simplify GetAllFields to use unified while+foreach (comment 2601399294) - Improve test assertions to check getter/setter in generated code (comments 2601422688, 2601424822, 2601426465) - Add test for m_ prefix support Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
- Check for handler pattern: new(static source => source, "PropertyName") - This is the useful assertion that validates property path in generated code - Updated all three ObservableProperty tests (Name, Title, Tags) Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
df71ebb to
cb00d50
Compare
…blePropertyAttribute (#33028) > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change Binding source generators now support properties generated by CommunityToolkit.Mvvm's `[ObservableProperty]` attribute. Previously, bindings failed because MAUI generators cannot see properties generated by other source generators. **Implementation** (following PR #32954 pattern for RelayCommand): - **BindingSourceGen/ITypeSymbolExtensions.cs**: Added `TryGetObservablePropertyType()` to detect fields with `[ObservableProperty]` and infer property types. Supports all three documented field naming patterns: `camelCase`, `_camelCase`, and `m_camelCase`. Includes validation for empty property names. - **BindingSourceGen/PathParser.cs**: Enhanced `TryHandleSpecialCases()` to handle ObservableProperty patterns as fallback when symbol resolution fails. - **BindingSourceGen/BindingSourceGenerator.cs**: Updated `GetLambdaReturnType()` to infer types from ObservableProperty fields, enabling C# lambda bindings. - **SourceGen/ITypeSymbolExtensions.cs**: Updated `TryGetProperty()` to check ObservableProperty-inferred properties, enabling XAML string-based bindings. - **Tests**: Added comprehensive unit tests in `BindingSourceGen.UnitTests` (8 tests) to validate ObservableProperty binding support across all field naming patterns and scenarios. Tests verify the generated binding code by checking: - Handler patterns: `new(static source => source, "PropertyName")` - validates property path in generated code - Setter expressions: `source.PropertyName = value;` - validates property assignment **Field Naming Pattern Support:** All three CommunityToolkit.Mvvm documented naming conventions are supported: - `name` → `Name` - `_name` → `Name` - `m_name` → `Name` **Works for both XAML and C# bindings:** ```csharp public class MyViewModel { [ObservableProperty] private string? name; // Generates Name property [ObservableProperty] private ObservableCollection<Tag> _tags = new(); // Generates Tags property [ObservableProperty] private int m_count; // Generates Count property } ``` ```xaml <Label Text="{Binding Name}" /> <ListView ItemsSource="{Binding Tags}" /> ``` ```csharp label.SetBinding(Label.TextProperty, static (MyViewModel vm) => vm.Name); listView.SetBinding(ListView.ItemsSourceProperty, static (MyViewModel vm) => vm.Tags); ``` ### Issues Fixed Fixes #32597 <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>[XSG][BindingSourceGen] Add support for CommunityToolkit.Mvvm ObservablePropertyAttribute source generator</issue_title> > <issue_description>Similar to #32597 > Related to #32953 > > The CommunityToolkit.Mvvm package contains a source generator which generates bindable property bolierplate code based on the `[ObservableProperty]` attribute: https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/generators/observableproperty > > Scenarios: > ```c# > // applied to a field > [ObservableProperty] > private string? name; > > // generated code: > /// <inheritdoc cref="_tags"/> > [global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.3.0.0")] > [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] > public global::System.Collections.ObjectModel.ObservableCollection<global::TestSampleContentBindings.Models.Tag> Tags > { > get => _tags; > [global::System.Diagnostics.CodeAnalysis.MemberNotNull("_tags")] > set > { > if (!global::System.Collections.Generic.EqualityComparer<global::System.Collections.ObjectModel.ObservableCollection<global::TestSampleContentBindings.Models.Tag>>.Default.Equals(_tags, value)) > { > OnTagsChanging(value); > OnTagsChanging(default, value); > OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.Tags); > _tags = value; > OnTagsChanged(value); > OnTagsChanged(default, value); > OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.Tags); > } > } > } > ``` > > Our source generators cannot see properties generated by other source generators, so the binding compilation will fail. > > Our sample content template uses this source generator and we are currently failing over to reflection-based bindings.</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes #32955 <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com> Co-authored-by: Simon Rozsival <simon@rozsival.com>
…blePropertyAttribute (#33028) > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change Binding source generators now support properties generated by CommunityToolkit.Mvvm's `[ObservableProperty]` attribute. Previously, bindings failed because MAUI generators cannot see properties generated by other source generators. **Implementation** (following PR #32954 pattern for RelayCommand): - **BindingSourceGen/ITypeSymbolExtensions.cs**: Added `TryGetObservablePropertyType()` to detect fields with `[ObservableProperty]` and infer property types. Supports all three documented field naming patterns: `camelCase`, `_camelCase`, and `m_camelCase`. Includes validation for empty property names. - **BindingSourceGen/PathParser.cs**: Enhanced `TryHandleSpecialCases()` to handle ObservableProperty patterns as fallback when symbol resolution fails. - **BindingSourceGen/BindingSourceGenerator.cs**: Updated `GetLambdaReturnType()` to infer types from ObservableProperty fields, enabling C# lambda bindings. - **SourceGen/ITypeSymbolExtensions.cs**: Updated `TryGetProperty()` to check ObservableProperty-inferred properties, enabling XAML string-based bindings. - **Tests**: Added comprehensive unit tests in `BindingSourceGen.UnitTests` (8 tests) to validate ObservableProperty binding support across all field naming patterns and scenarios. Tests verify the generated binding code by checking: - Handler patterns: `new(static source => source, "PropertyName")` - validates property path in generated code - Setter expressions: `source.PropertyName = value;` - validates property assignment **Field Naming Pattern Support:** All three CommunityToolkit.Mvvm documented naming conventions are supported: - `name` → `Name` - `_name` → `Name` - `m_name` → `Name` **Works for both XAML and C# bindings:** ```csharp public class MyViewModel { [ObservableProperty] private string? name; // Generates Name property [ObservableProperty] private ObservableCollection<Tag> _tags = new(); // Generates Tags property [ObservableProperty] private int m_count; // Generates Count property } ``` ```xaml <Label Text="{Binding Name}" /> <ListView ItemsSource="{Binding Tags}" /> ``` ```csharp label.SetBinding(Label.TextProperty, static (MyViewModel vm) => vm.Name); listView.SetBinding(ListView.ItemsSourceProperty, static (MyViewModel vm) => vm.Tags); ``` ### Issues Fixed Fixes #32597 <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>[XSG][BindingSourceGen] Add support for CommunityToolkit.Mvvm ObservablePropertyAttribute source generator</issue_title> > <issue_description>Similar to #32597 > Related to #32953 > > The CommunityToolkit.Mvvm package contains a source generator which generates bindable property bolierplate code based on the `[ObservableProperty]` attribute: https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/generators/observableproperty > > Scenarios: > ```c# > // applied to a field > [ObservableProperty] > private string? name; > > // generated code: > /// <inheritdoc cref="_tags"/> > [global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.3.0.0")] > [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] > public global::System.Collections.ObjectModel.ObservableCollection<global::TestSampleContentBindings.Models.Tag> Tags > { > get => _tags; > [global::System.Diagnostics.CodeAnalysis.MemberNotNull("_tags")] > set > { > if (!global::System.Collections.Generic.EqualityComparer<global::System.Collections.ObjectModel.ObservableCollection<global::TestSampleContentBindings.Models.Tag>>.Default.Equals(_tags, value)) > { > OnTagsChanging(value); > OnTagsChanging(default, value); > OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.Tags); > _tags = value; > OnTagsChanged(value); > OnTagsChanged(default, value); > OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.Tags); > } > } > } > ``` > > Our source generators cannot see properties generated by other source generators, so the binding compilation will fail. > > Our sample content template uses this source generator and we are currently failing over to reflection-based bindings.</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes #32955 <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com> Co-authored-by: Simon Rozsival <simon@rozsival.com>
…blePropertyAttribute (#33028) > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change Binding source generators now support properties generated by CommunityToolkit.Mvvm's `[ObservableProperty]` attribute. Previously, bindings failed because MAUI generators cannot see properties generated by other source generators. **Implementation** (following PR #32954 pattern for RelayCommand): - **BindingSourceGen/ITypeSymbolExtensions.cs**: Added `TryGetObservablePropertyType()` to detect fields with `[ObservableProperty]` and infer property types. Supports all three documented field naming patterns: `camelCase`, `_camelCase`, and `m_camelCase`. Includes validation for empty property names. - **BindingSourceGen/PathParser.cs**: Enhanced `TryHandleSpecialCases()` to handle ObservableProperty patterns as fallback when symbol resolution fails. - **BindingSourceGen/BindingSourceGenerator.cs**: Updated `GetLambdaReturnType()` to infer types from ObservableProperty fields, enabling C# lambda bindings. - **SourceGen/ITypeSymbolExtensions.cs**: Updated `TryGetProperty()` to check ObservableProperty-inferred properties, enabling XAML string-based bindings. - **Tests**: Added comprehensive unit tests in `BindingSourceGen.UnitTests` (8 tests) to validate ObservableProperty binding support across all field naming patterns and scenarios. Tests verify the generated binding code by checking: - Handler patterns: `new(static source => source, "PropertyName")` - validates property path in generated code - Setter expressions: `source.PropertyName = value;` - validates property assignment **Field Naming Pattern Support:** All three CommunityToolkit.Mvvm documented naming conventions are supported: - `name` → `Name` - `_name` → `Name` - `m_name` → `Name` **Works for both XAML and C# bindings:** ```csharp public class MyViewModel { [ObservableProperty] private string? name; // Generates Name property [ObservableProperty] private ObservableCollection<Tag> _tags = new(); // Generates Tags property [ObservableProperty] private int m_count; // Generates Count property } ``` ```xaml <Label Text="{Binding Name}" /> <ListView ItemsSource="{Binding Tags}" /> ``` ```csharp label.SetBinding(Label.TextProperty, static (MyViewModel vm) => vm.Name); listView.SetBinding(ListView.ItemsSourceProperty, static (MyViewModel vm) => vm.Tags); ``` ### Issues Fixed Fixes #32597 <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>[XSG][BindingSourceGen] Add support for CommunityToolkit.Mvvm ObservablePropertyAttribute source generator</issue_title> > <issue_description>Similar to #32597 > Related to #32953 > > The CommunityToolkit.Mvvm package contains a source generator which generates bindable property bolierplate code based on the `[ObservableProperty]` attribute: https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/generators/observableproperty > > Scenarios: > ```c# > // applied to a field > [ObservableProperty] > private string? name; > > // generated code: > /// <inheritdoc cref="_tags"/> > [global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.3.0.0")] > [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] > public global::System.Collections.ObjectModel.ObservableCollection<global::TestSampleContentBindings.Models.Tag> Tags > { > get => _tags; > [global::System.Diagnostics.CodeAnalysis.MemberNotNull("_tags")] > set > { > if (!global::System.Collections.Generic.EqualityComparer<global::System.Collections.ObjectModel.ObservableCollection<global::TestSampleContentBindings.Models.Tag>>.Default.Equals(_tags, value)) > { > OnTagsChanging(value); > OnTagsChanging(default, value); > OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.Tags); > _tags = value; > OnTagsChanged(value); > OnTagsChanged(default, value); > OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.Tags); > } > } > } > ``` > > Our source generators cannot see properties generated by other source generators, so the binding compilation will fail. > > Our sample content template uses this source generator and we are currently failing over to reflection-based bindings.</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes #32955 <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com> Co-authored-by: Simon Rozsival <simon@rozsival.com>
…blePropertyAttribute (#33028) > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change Binding source generators now support properties generated by CommunityToolkit.Mvvm's `[ObservableProperty]` attribute. Previously, bindings failed because MAUI generators cannot see properties generated by other source generators. **Implementation** (following PR #32954 pattern for RelayCommand): - **BindingSourceGen/ITypeSymbolExtensions.cs**: Added `TryGetObservablePropertyType()` to detect fields with `[ObservableProperty]` and infer property types. Supports all three documented field naming patterns: `camelCase`, `_camelCase`, and `m_camelCase`. Includes validation for empty property names. - **BindingSourceGen/PathParser.cs**: Enhanced `TryHandleSpecialCases()` to handle ObservableProperty patterns as fallback when symbol resolution fails. - **BindingSourceGen/BindingSourceGenerator.cs**: Updated `GetLambdaReturnType()` to infer types from ObservableProperty fields, enabling C# lambda bindings. - **SourceGen/ITypeSymbolExtensions.cs**: Updated `TryGetProperty()` to check ObservableProperty-inferred properties, enabling XAML string-based bindings. - **Tests**: Added comprehensive unit tests in `BindingSourceGen.UnitTests` (8 tests) to validate ObservableProperty binding support across all field naming patterns and scenarios. Tests verify the generated binding code by checking: - Handler patterns: `new(static source => source, "PropertyName")` - validates property path in generated code - Setter expressions: `source.PropertyName = value;` - validates property assignment **Field Naming Pattern Support:** All three CommunityToolkit.Mvvm documented naming conventions are supported: - `name` → `Name` - `_name` → `Name` - `m_name` → `Name` **Works for both XAML and C# bindings:** ```csharp public class MyViewModel { [ObservableProperty] private string? name; // Generates Name property [ObservableProperty] private ObservableCollection<Tag> _tags = new(); // Generates Tags property [ObservableProperty] private int m_count; // Generates Count property } ``` ```xaml <Label Text="{Binding Name}" /> <ListView ItemsSource="{Binding Tags}" /> ``` ```csharp label.SetBinding(Label.TextProperty, static (MyViewModel vm) => vm.Name); listView.SetBinding(ListView.ItemsSourceProperty, static (MyViewModel vm) => vm.Tags); ``` ### Issues Fixed Fixes #32597 <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>[XSG][BindingSourceGen] Add support for CommunityToolkit.Mvvm ObservablePropertyAttribute source generator</issue_title> > <issue_description>Similar to #32597 > Related to #32953 > > The CommunityToolkit.Mvvm package contains a source generator which generates bindable property bolierplate code based on the `[ObservableProperty]` attribute: https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/generators/observableproperty > > Scenarios: > ```c# > // applied to a field > [ObservableProperty] > private string? name; > > // generated code: > /// <inheritdoc cref="_tags"/> > [global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.3.0.0")] > [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] > public global::System.Collections.ObjectModel.ObservableCollection<global::TestSampleContentBindings.Models.Tag> Tags > { > get => _tags; > [global::System.Diagnostics.CodeAnalysis.MemberNotNull("_tags")] > set > { > if (!global::System.Collections.Generic.EqualityComparer<global::System.Collections.ObjectModel.ObservableCollection<global::TestSampleContentBindings.Models.Tag>>.Default.Equals(_tags, value)) > { > OnTagsChanging(value); > OnTagsChanging(default, value); > OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.Tags); > _tags = value; > OnTagsChanged(value); > OnTagsChanged(default, value); > OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.Tags); > } > } > } > ``` > > Our source generators cannot see properties generated by other source generators, so the binding compilation will fail. > > Our sample content template uses this source generator and we are currently failing over to reflection-based bindings.</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes #32955 <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com> Co-authored-by: Simon Rozsival <simon@rozsival.com>
…blePropertyAttribute (#33028) > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change Binding source generators now support properties generated by CommunityToolkit.Mvvm's `[ObservableProperty]` attribute. Previously, bindings failed because MAUI generators cannot see properties generated by other source generators. **Implementation** (following PR #32954 pattern for RelayCommand): - **BindingSourceGen/ITypeSymbolExtensions.cs**: Added `TryGetObservablePropertyType()` to detect fields with `[ObservableProperty]` and infer property types. Supports all three documented field naming patterns: `camelCase`, `_camelCase`, and `m_camelCase`. Includes validation for empty property names. - **BindingSourceGen/PathParser.cs**: Enhanced `TryHandleSpecialCases()` to handle ObservableProperty patterns as fallback when symbol resolution fails. - **BindingSourceGen/BindingSourceGenerator.cs**: Updated `GetLambdaReturnType()` to infer types from ObservableProperty fields, enabling C# lambda bindings. - **SourceGen/ITypeSymbolExtensions.cs**: Updated `TryGetProperty()` to check ObservableProperty-inferred properties, enabling XAML string-based bindings. - **Tests**: Added comprehensive unit tests in `BindingSourceGen.UnitTests` (8 tests) to validate ObservableProperty binding support across all field naming patterns and scenarios. Tests verify the generated binding code by checking: - Handler patterns: `new(static source => source, "PropertyName")` - validates property path in generated code - Setter expressions: `source.PropertyName = value;` - validates property assignment **Field Naming Pattern Support:** All three CommunityToolkit.Mvvm documented naming conventions are supported: - `name` → `Name` - `_name` → `Name` - `m_name` → `Name` **Works for both XAML and C# bindings:** ```csharp public class MyViewModel { [ObservableProperty] private string? name; // Generates Name property [ObservableProperty] private ObservableCollection<Tag> _tags = new(); // Generates Tags property [ObservableProperty] private int m_count; // Generates Count property } ``` ```xaml <Label Text="{Binding Name}" /> <ListView ItemsSource="{Binding Tags}" /> ``` ```csharp label.SetBinding(Label.TextProperty, static (MyViewModel vm) => vm.Name); listView.SetBinding(ListView.ItemsSourceProperty, static (MyViewModel vm) => vm.Tags); ``` ### Issues Fixed Fixes #32597 <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>[XSG][BindingSourceGen] Add support for CommunityToolkit.Mvvm ObservablePropertyAttribute source generator</issue_title> > <issue_description>Similar to #32597 > Related to #32953 > > The CommunityToolkit.Mvvm package contains a source generator which generates bindable property bolierplate code based on the `[ObservableProperty]` attribute: https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/generators/observableproperty > > Scenarios: > ```c# > // applied to a field > [ObservableProperty] > private string? name; > > // generated code: > /// <inheritdoc cref="_tags"/> > [global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.3.0.0")] > [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] > public global::System.Collections.ObjectModel.ObservableCollection<global::TestSampleContentBindings.Models.Tag> Tags > { > get => _tags; > [global::System.Diagnostics.CodeAnalysis.MemberNotNull("_tags")] > set > { > if (!global::System.Collections.Generic.EqualityComparer<global::System.Collections.ObjectModel.ObservableCollection<global::TestSampleContentBindings.Models.Tag>>.Default.Equals(_tags, value)) > { > OnTagsChanging(value); > OnTagsChanging(default, value); > OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.Tags); > _tags = value; > OnTagsChanged(value); > OnTagsChanged(default, value); > OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.Tags); > } > } > } > ``` > > Our source generators cannot see properties generated by other source generators, so the binding compilation will fail. > > Our sample content template uses this source generator and we are currently failing over to reflection-based bindings.</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes #32955 <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com> Co-authored-by: Simon Rozsival <simon@rozsival.com>
## What's Coming .NET MAUI inflight/candidate introduces significant improvements across all platforms with focus on quality, performance, and developer experience. This release includes 16 commits with various improvements, bug fixes, and enhancements. ## Checkbox - [Android] Implement material3 support for CheckBox by @HarishwaranVijayakumar in #33339 <details> <summary>🔧 Fixes</summary> - [Implement Material3 Support for CheckBox](#33338) </details> ## CollectionView - [Android] Fixed EmptyView doesn’t display when CollectionView is placed inside a VerticalStackLayout by @NanthiniMahalingam in #33134 <details> <summary>🔧 Fixes</summary> - [CollectionView does not show an EmptyView template with an empty collection](#32932) </details> ## Essentials - [Windows]Fix NullReferenceException in OpenReadAsync for FileResult created with full path by @devanathan-vaithiyanathan in #28238 <details> <summary>🔧 Fixes</summary> - [[Windows] FileResult(string fullPath) not initialized properly](#26858) </details> ## Image - Fix Glide IllegalArgumentException in MauiCustomTarget.clear() for destroyed activities by @jfversluis via @Copilot in #29780 <details> <summary>🔧 Fixes</summary> - [java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity - glide](#29699) </details> ## Label - [Android] Fix for Label WordWrap width issue causing HorizontalOptions misalignment by @praveenkumarkarunanithi in #33281 <details> <summary>🔧 Fixes</summary> - [[Android] Unexpected Line Breaks in Android, Label with WordWrap Mode Due to Trailing Space.](#31782) - [Label not sized correctly on Android](#27614) </details> - Fix to Improve Flyout Accessibility by Adjusting UITableViewController Labels by @SuthiYuvaraj in #31619 <details> <summary>🔧 Fixes</summary> - [Navigation section present under hamburger are programmatically define as table :A11y_.NET maui_User can get all the insights of Dashboard_Devtools](#30894) </details> ## Mediapicker - [Regression][iOS] Fix MediaPicker PickPhotosAsync getting file name in contentType property by @devanathan-vaithiyanathan in #33390 <details> <summary>🔧 Fixes</summary> - [[iOS] MediaPicker PickPhotosAsync getting file name in contentType property](#33348) </details> ## Navigation - Fix handler not disconnected when removing non visible pages using RemovePage() by @Vignesh-SF3580 in #32289 <details> <summary>🔧 Fixes</summary> - [NavigationPage.Navigation.RemovePage() fails to disconnect handlers when removing pages, unlike ContentPage.Navigation.RemovePage()](#32239) </details> ## Picker - [Android] Fix Picker IsOpen not reset when picker is dismissed by @devanathan-vaithiyanathan in #33332 <details> <summary>🔧 Fixes</summary> - [[Android] Picker IsOpen not reset when picker is dismissed](#33331) </details> ## Shell - [iOS & Catalyst ] Fixed IsEnabled property should work on Tabs by @SubhikshaSf4851 in #33369 <details> <summary>🔧 Fixes</summary> - [[Catalyst] TabBarBackgroundColor, TabBarUnselectedColor, and IsEnabled Not Working as Expected in Shell](#33158) </details> - [iOS,Windows] Fix navigation bar colors not resetting when switching ShellContent by @Vignesh-SF3580 in #33228 <details> <summary>🔧 Fixes</summary> - [[iOS, Windows] Shell Navigation bar colors are not updated correctly when switching ShellContent](#33227) </details> - [iOS] Fixed Shell navigation on search handler suggestion selection by @SubhikshaSf4851 in #33406 <details> <summary>🔧 Fixes</summary> - [[iOS] Clicking on search suggestions fails to navigate to detail page correctly](#33356) </details> ## Templates - Fix VoiceOver doesnot announces the State of the ComboBox by @SuthiYuvaraj in #32286 ## Xaml - [XSG][BindingSourceGen] Add support for CommunityToolkit.Mvvm ObservablePropertyAttribute by @simonrozsival via @Copilot in #33028 <details> <summary>🔧 Fixes</summary> - [[XSG] Add heuristic to support bindable properties generated by other source generators](#32597) </details> <details> <summary>📦 Other (2)</summary> - [XSG] Improve diagnostic reporting during binding compilation by @simonrozsival via @Copilot in #32905 - [Testing] Fixed Test case failure in PR 33574 - [01/19/2026] Candidate - 1 by @TamilarasanSF4853 in #33602 </details> **Full Changelog**: main...inflight/candidate
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Description of Change
Binding source generators now support properties generated by CommunityToolkit.Mvvm's
[ObservableProperty]attribute. Previously, bindings failed because MAUI generators cannot see properties generated by other source generators.Implementation (following PR #32954 pattern for RelayCommand):
BindingSourceGen/ITypeSymbolExtensions.cs: Added
TryGetObservablePropertyType()to detect fields with[ObservableProperty]and infer property types. Supports all three documented field naming patterns:camelCase,_camelCase, andm_camelCase. Includes validation for empty property names.BindingSourceGen/PathParser.cs: Enhanced
TryHandleSpecialCases()to handle ObservableProperty patterns as fallback when symbol resolution fails.BindingSourceGen/BindingSourceGenerator.cs: Updated
GetLambdaReturnType()to infer types from ObservableProperty fields, enabling C# lambda bindings.SourceGen/ITypeSymbolExtensions.cs: Updated
TryGetProperty()to check ObservableProperty-inferred properties, enabling XAML string-based bindings.Tests: Added comprehensive unit tests in
BindingSourceGen.UnitTests(8 tests) to validate ObservableProperty binding support across all field naming patterns and scenarios. Tests verify the generated binding code by checking:new(static source => source, "PropertyName")- validates property path in generated codesource.PropertyName = value;- validates property assignmentField Naming Pattern Support:
All three CommunityToolkit.Mvvm documented naming conventions are supported:
name→Name_name→Namem_name→NameWorks for both XAML and C# bindings:
Issues Fixed
Fixes #32597
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.