Conversation
There was a problem hiding this comment.
Pull request overview
This is a release candidate pull request dated "January 19th, Candidate" containing multiple bug fixes, accessibility improvements, test additions, and code formatting changes. The PR addresses several issues across different areas of the .NET MAUI framework including UI testing infrastructure, template accessibility, platform handlers, and navigation.
Changes:
- Added comprehensive UI test infrastructure improvements with new helper methods and test cases for Shell, Picker, CollectionView, and Label
- Enhanced accessibility in MAUI mobile template with improved semantic properties and screen reader announcements for picker controls
- Fixed critical platform-specific bugs including Android checkbox theming, Windows toolbar color clearing, Picker IsOpen state, and Label text measurement
- Added source generator unit tests for indexer bindings and observable property support
- Code formatting and whitespace cleanup across multiple XAML processing files
Reviewed changes
Copilot reviewed 65 out of 101 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/TestUtils/src/UITest.Appium/HelperExtensions.cs | Added ClosePicker() helper for cross-platform picker dismissal |
| src/Templates/src/templates/maui-mobile/Pages/*.xaml | Improved accessibility with better semantic descriptions for picker controls |
| src/Templates/src/templates/maui-mobile/PageModels/*.cs | Added screen reader announcements for picker state changes |
| src/Templates/src/templates/maui-mobile/AppShell.xaml | Added semantic properties to shell content navigation items |
| src/Graphics/src/Graphics/ColorUtils.cs | Whitespace cleanup |
| src/Essentials/test/DeviceTests/Tests/FileSystem_Tests.cs | Added tests for FileResult with file paths and multiple stream reads |
| src/Essentials/src/MediaPicker/MediaPicker.ios.cs | Fixed FileResult creation to preserve FileName and ContentType |
| src/Essentials/src/FileSystem/FileSystem.windows.cs | Fixed FileResult.OpenReadAsync to handle null File property |
| src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt | Added LabelHandler.GetDesiredSize API entry |
| src/Core/src/Platform/Windows/MauiToolbar.xaml.cs | Fixed toolbar foreground color clearing when null |
| src/Core/src/Platform/Android/CheckBoxExtensions.cs | Fixed Material 3 checkbox theming with cached default tints |
| src/Core/src/Handlers/Picker/PickerHandler.Android.cs | Fixed IsOpen state synchronization on dialog dismiss |
| src/Core/src/Handlers/Label/LabelHandler.Android.cs | Fixed multi-line label width measurement for non-Fill alignment |
| src/Core/AndroidNative/maui/.../MauiCustomTarget.java | Added context destruction checks before Glide operations |
| src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj | Added MAUIG2045 to warnings suppressions |
| src/Controls/tests/TestCases..Tests/snapshots//*.png | Added screenshot baselines for ShellColorsResetOnNavigation test |
| src/Controls/tests/TestCases.Shared.Tests/UtilExtensions.cs | Added TapFirstSearchResult helper for SearchHandler testing |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/*.cs | Added UI tests for Issues 33356, 33331, 33227, 33158, 32932, 31782 |
| src/Controls/tests/TestCases.HostApp/Issues/*.cs | Added test pages for the corresponding issue tests |
| src/Controls/tests/SourceGen.UnitTests/InitializeComponent/IndexerBindings.cs | Added comprehensive indexer binding tests |
| src/Controls/tests/SourceGen.UnitTests/BindingDiagnosticsTests.cs | Added diagnostic verification tests |
| src/Controls/tests/Core.UnitTests/ShellNavigatingTests.cs | Added test for RemovePage disconnecting handlers in Shell |
| src/Controls/tests/Core.UnitTests/NavigationUnitTest.cs | Added tests for RemovePage disconnecting handlers |
| src/Controls/tests/BindingSourceGen.UnitTests/ObservablePropertyTests.cs | Added tests for CommunityToolkit.Mvvm ObservableProperty support |
| src/Controls/src/Xaml/*.cs | Code formatting and whitespace cleanup |
Files not reviewed (1)
- src/Controls/src/SourceGen/xlf/MauiGResources.Designer.cs: Language not supported
| /// <param name="app">Represents the main gateway to interact with an app.</param> | ||
| /// <param name="x">Optional X coordinate for Windows tap. Default is 0.</param> | ||
| /// <param name="y">Optional Y coordinate for Windows tap. Default is 0.</param> | ||
| public static void ClosePicker(this IApp app, int windowsTapx = 0, int windowsTapy = 0) |
There was a problem hiding this comment.
Parameter names 'windowsTapx' and 'windowsTapy' have inconsistent casing. Should be 'windowsTapX' and 'windowsTapY' following PascalCase convention for parameter names, or rename to 'windowsX' and 'windowsY' for brevity.
| else if (app is AppiumWindowsApp) | ||
| { | ||
| if (windowsTapx != 0 || windowsTapy != 0) | ||
| { | ||
| app.TapCoordinates(windowsTapx, windowsTapy); | ||
| } | ||
| } |
There was a problem hiding this comment.
Windows platform does nothing when coordinates are (0, 0). This creates inconsistent behavior - the method should either always tap a default location on Windows (like 'Cancel' button) or document why coordinates are required. Consider adding a default tap action or throwing an exception when coordinates are not provided.
| OnPropertyChanged(nameof(HasCompletedTasks)); | ||
| } | ||
|
|
||
| partial void OnIsCategoryPickerExpandedChanged(bool value) |
There was a problem hiding this comment.
Extra space between 'void' and 'OnIsCategoryPickerExpandedChanged' - should be single space.
| AColor tintColor2 = accent.ToPlatform(); | ||
| return ColorStateListExtensions.CreateCheckBox(tintColor2); |
There was a problem hiding this comment.
Variable name 'tintColor2' is unclear. Should be renamed to 'accentTintColor' or 'fallbackTintColor' to better describe its purpose.
| { | ||
| // Android does not support selecting elements in SearchHandler results | ||
| var y = searchHandler.GetRect().Y + searchHandler.GetRect().Height; | ||
| app.TapCoordinates(searchHandler.GetRect().X + 10, y + 10); |
There was a problem hiding this comment.
Magic numbers 10 used for coordinate offsets without explanation. Consider adding constants like 'DefaultTapOffset = 10' with documentation explaining why this offset is needed.
| @@ -0,0 +1,30 @@ | |||
| #if TEST_FAILS_ON_WINDOWS // Existing PR for windows - https://github.com/dotnet/maui/pull/26728 | |||
There was a problem hiding this comment.
Comment references PR #26728 for Windows failure, but the test is entirely excluded with preprocessor directive. If there's a Windows-specific fix pending, consider structuring the test to skip only Windows assertions rather than excluding the entire test file from compilation.
|
|
||
| // For arrays, the handler should use empty string for indexer name (no property to listen to on the array itself) | ||
| // The array itself can't notify about element changes - only the containing property can | ||
| Assert.Contains("new(static source => source, \"Names\")", generated, StringComparison.Ordinal); |
There was a problem hiding this comment.
The test comment on line 310-311 says 'handler should use empty string for indexer name' but the assertion checks for 'Names' property handler. This appears contradictory - either the comment or the assertion may be incorrect.
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
…e - 1 (#33602) This PR addresses the UI test image failures that occurred in the inflight/candidate branch #33574 and includes updates to improve rendering and test stability across platforms. - Resaved snapshots for these test cases due to this PR fix #33281: CanvasShouldHonorBlur, VerifyScrollViewWithScrollToPositionCenterAndGridContent, VerifyScrollViewWithRTLAndGridContent, VerifyScrollViewWithScrollToPositionEndAndGridContent, VerifyScrollViewWithScrollToPositionMakeVisibleAndGridContent, VerifyScrollViewWithScrollToPositionStartAndGridContent, DownSizeImageAppearProperly, Issue30440ImageShouldClipCorrectly, IndicatorViewWithTemplatedIcon, VerifyCarouselLayoutOrientationChange, VerifyCarouselViewItemsSourceClearedDynamically, EmptyViewShouldDisplayWhenCollectionViewIsInsideVerticalStackLayout. - Issue18751Test - Added the failing condition for Android due to the image not loading on CI. Already restricted for other platforms; now it fails on Android as well. - Issue18751Test - Added the failing condition for Windows due to AutomationId not working on layout in Appium. - VariousSpanGesturePermutation - Increased the tap coordinates due to this PR fix #33281 changes. --------- Co-authored-by: sheiksyedm <sheiksyedm@syncfusion.com>
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
…s misalignment (#33281) ### Root Cause On Android, for `Label` controls with `LineBreakMode="WordWrap"` and multiple lines, `GetDesiredSize()` returns the full constraint width instead of the actual rendered text width. This causes extra trailing space and incorrect horizontal alignment when `HorizontalLayoutAlignment` is set to `Start`, `Center`, or `End`. Single-line and Fill alignment cases are unaffected. ### Description of Change Updated `GetDesiredSize()` in `LabelHandler.Android.cs` to calculate the actual content width for wrapped, multi-line labels with non-Fill alignment. The implementation determines the widest rendered line using `layout.GetLineWidth(i)` and uses that value (plus padding) as the desired width. ### Issues Fixed Fixes #31782 Fixes #27614 Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Output Video | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/0eca49ce-3cfd-4f42-85cb-98560385a056" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/a1cba4c6-d422-46ab-96ae-db0dc6dc0dc9" /> |
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Root Cause The load-time handling of the `IsEnabled` property for tab items was not implemented on iOS. As a result, disabled tabs could still be selectable and navigateable ### Description of Change Updated `ShellItemRenderer.cs` to set the `IsEnabled` property of each `TabBar` item based on the corresponding `IsEnabled` value during both initial creation and when the items collection changes. <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33158 ### Follow-up PR : - On **iOS 26** and **Catalyst 26**, navigation between tabs via drag and selection gestures is handled separately in this PR #33337. ### Tested the behavior in the following platforms - [ ] Windows - [x] Android - [x] iOS - [x] Mac | Before Issue Fix | After Issue Fix | |----------|----------| | <video src="https://github.com/user-attachments/assets/d133ccd3-abb1-44dd-9135-16b1ebeeb8e6"> | <video src="https://github.com/user-attachments/assets/223f454c-fc1a-4167-b265-8ef6c7e0c8c6"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details When the Picker dialog is closed using the cancel button or tapping outside, the IsOpen property is not updated. Even though the Picker is no longer visible, IsOpen stays true, causing the Picker state to be incorrect. ### Description of Change Updated the Android Picker handler to reset VirtualView.IsOpen to false when the picker dialog is dismissed. <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33331 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <video src="https://github.com/user-attachments/assets/5dc18c5f-a2d2-48cd-95eb-d150b210c4ce" width="300" height="600"> | **Android**<br> <video src="https://github.com/user-attachments/assets/c30f015d-5d2b-46cc-9bc1-d07ba9ed485c" width="300" height="600"> |
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Description of Change This pull request updates the way checkbox tint colors are handled on Android, improving compatibility with both Material 2 and Material 3 themes. The main focus is on ensuring that the correct default or accent color is used for checkbox foregrounds depending on the Material version in use. **Theme-aware checkbox tinting:** * Introduced a static field `_defaultButtonTintList` in `CheckBoxExtensions` to cache the default button tint for Material 3 themes, ensuring consistent appearance and avoiding unnecessary recomputation. * Updated the `GetColorStateList` method to: - Use the default theme's button tint when Material 3 is enabled, falling back to the cached `_defaultButtonTintList` if available. - Continue using the accent color for Material 2 themes, preserving existing behavior. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33338 ### Screenshots Material Design Spec - [CheckBox](https://m3.material.io/components/checkbox/specs) | Material 2 | Material 3 | |----------|----------| | <img src="https://github.com/user-attachments/assets/8bce9689-a698-49af-862f-24e56ec4f3cb"> | <img src="https://github.com/user-attachments/assets/978b27eb-0e67-451c-8a3b-927434d6389a"> | --------- Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
…movePage() (#32289) <!-- Please let the below note in for people that find this PR --> > [!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! ### Issue Details When a non-visible page is removed from the navigation stack using RemovePage(), its handler is not disconnected. ### Root Cause The RemovePage() method removes the page from the navigation stack but does not explicitly disconnect its handler. ### Description of Change The handler is now properly disconnected when a page is removed using RemovePage(). Regression PR: #24887 ### Tested the behavior in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed Fixes #32239 ### Screenshots **Android:** | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="300" height="600" src="https://github.com/user-attachments/assets/890c3e4b-f520-4826-b942-6ec9e04233d1"> | <video width="300" height="600" src="https://github.com/user-attachments/assets/40ebc025-7298-4b43-8816-4932a01fb563">) | **iOS:** | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="300" height="600" src="https://github.com/user-attachments/assets/484e17cd-bd83-415e-af27-99acf893b203"> | <video width="300" height="600" src="https://github.com/user-attachments/assets/062a1c6d-047c-4bde-add2-d2d261763c87">) | --------- Co-authored-by: Stephane Delcroix <stephane@delcroix.org> Co-authored-by: Rui Marinho <me@ruimarinho.net> Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
…ShellContent (#33228) ### Issue details When switching between ShellContent items, navigation bar colors from the previously displayed page are incorrectly applied to the next page, even when the next page does not define any navigation bar colors. On iOS, background and title colors persist across pages. On Windows, the issue is limited to TitleColor, which remains applied when navigating to an uncolored page. ### Root cause iOS: Navigation bar appearance is applied via SetAppearance in ShellNavBarAppearanceTracker when colors are specified. However, when navigating to a page without defined colors, the appearance is not reset, causing previously applied colors to persist. Windows: The toolbar title foreground is updated only when a brush is provided. When switching to a page without a TitleColor, the previous brush is not cleared, so the title color remains. ### Description of change iOS: Reset the navigation bar appearance to the default native appearance when no colors are specified, ensuring that colors from a previous page are not carried over. Windows: Clear the toolbar title foreground when the brush is null, allowing the title color to revert to the system default instead of retaining the previous color. ### Tested the behavior in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed Fixes #33227 ### Screenshots | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="300" height="600" src="https://github.com/user-attachments/assets/0665c21a-f3b9-44e1-bb95-05678560ac73"> | <video width="300" height="600" src="https://github.com/user-attachments/assets/29758b20-8bb4-4393-8936-5b7ccd06aab8">) | | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="300" height="600" src="https://github.com/user-attachments/assets/3fd239fe-1b21-4ddb-8982-ed4939b47ab9"> | <video width="300" height="600" src="https://github.com/user-attachments/assets/f87c760e-3d24-4a53-b96c-1bf23b818482">) |
…reated with full path (#28238) ### Issue details Calling OpenReadAsync() on a FileResult constructed using the full path constructor throws a NullReferenceException with the message: "Value cannot be null. (Parameter 'windowsRuntimeFile')". This occurs because the internal File property is null when a full path is provided. ### Description of Change The changes fix the Exception in OpenReadAsync() by properly initializing the File property when a FileResult is created with a full path. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #26858 **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Windows**<br> <img src="https://github.com/user-attachments/assets/d0fd9a0f-7b7a-4c15-a15f-69f978060067" > |**Windows**<br> <img src="https://github.com/user-attachments/assets/0059d3d6-6350-487a-a8be-618cc6221b1e" > | --------- Co-authored-by: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com>
…r Labels (#31619) <!-- Please let the below note in for people that find this PR --> > [!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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Description: The Shell Flyout is implemented using a `UITableViewController` with a `UITableView`, which iOS accessibility services announce as a "table". ### Description of Change: Entirely hides the UITableView Accessibility and makes the UIContainerCell to become a first responder, The inner UIContainerCell cannot be individually detected — it is treated as a single grouped element. ### Issues Fixed Fixes #30894 ### Tested the behaviour in the following platforms - [ ] Android - [ ] Windows - [ ] iOS - [x] Mac ### Output Screenshot Before Issue Fix | After Issue Fix | |----------|----------| |<video width="300" height="150" alt="Before Fix" src="https://github.com/user-attachments/assets/1862862a-ffee-4302-a46f-5ac083e39a0b">|<video width="300" height="150" alt="After Fix" src ="https://github.com/user-attachments/assets/be969437-d5ea-4319-ac19-9b60bd0e1a68">|
…ced inside a VerticalStackLayout (#33134) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Root Cause - When the RecyclerView height is infinite, the EmptyView also receives an infinite height constraint. During measurement, Int.MAX_VALUE is assigned to represent this infinite height. - However, while converting the RecyclerView’s infinite height to an integer value, a pixel conversion issue occurs. As a result, the EmptyView fails to render correctly and does not appear on the screen. ### Description of Change - When the EmptyView height is infinite, the EmptyView is measured to the exact infinite height when its height is set to Int.MAX_VALUE Validated the behaviour in the following platforms - [x] Android - [x] Windows , - [x] iOS, - [x] MacOS ### Issues Fixed Fixes #32932 ### Output **Android** |Before|After| |--|--| | <video src="https://github.com/user-attachments/assets/e1bc87a9-cb07-4e08-86aa-f64159cdcd15" >| <video src="https://github.com/user-attachments/assets/1b89e70d-b93d-4c1f-9e0d-af9db32dbd7b">| --------- Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
- [x] Analyze the issue - understand TODOs in binding compilation logic - [x] Identify files to modify: `CompiledBindingMarkup.cs`, `KnownMarkups.cs`, `Descriptors.cs`, `MauiGResources.resx`, etc. - [x] Build and test baseline (100 tests passing) - [x] Add new diagnostic descriptors for binding-related errors (matching XamlC error codes) - MAUIG2041: BindingIndexerNotClosed (matching XC0041) - MAUIG2042: BindingIndexerEmpty (matching XC0042) - MAUIG2043: BindingIndexerTypeUnsupported (matching XC0043) - MAUIG2045: BindingPropertyNotFound (matching XC0045) - MAUIG2024: BindingWithXDataTypeFromOuterScope warning (matching XC0024) - MAUIG2064: NamescopeDuplicate (matching XC0064) - [x] Replace `return false; // TODO report diagnostic` with actual diagnostic reporting - [x] Replace `throw new Exception` with diagnostic reporting - [x] Update resource strings to match XamlC messages - [x] Add unit tests for the new diagnostics (6 tests) - [x] Update AnalyzerReleases.Unshipped.md - [x] Build and test (147 tests passing) - [x] Run code review and address feedback - [x] Run CodeQL checker (no security issues found) - [x] Revert unrelated formatting changes - [x] Fix alignment in Descriptors.cs - [x] Change diagnostic prefix from MAUIX to MAUIG per reviewer feedback - [x] Remove unreachable code in CompiledBindingMarkup.cs - [x] Add missing test scenarios for MAUIG2024 and MAUIG2043 diagnostics - [x] Support NoWarn metadata for source generator diagnostics - [x] Add MAUIG2045 to NoWarn for test XAML files with intentional binding errors - [x] Address latest code review feedback: - Refactored repeated indexer lookup pattern into reusable local function - Removed localized message checks from diagnostic tests - Fixed IndexerBindings test assertions to properly validate lambda context using regex patterns that match actual generated code structure <!-- START COPILOT CODING AGENT SUFFIX --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>[XSG] Improve diagnostic reporting during binding compilation</issue_title> > <issue_description>We left several todos in the binding compilation logic in the XAML source generator. We should try to match the warnings and errors produced by XamlC, just with an adjusted error code.</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> - Fixes #32904 <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- 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>
…n contentType property (#33390) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details The FileResult constructor was being called with (filePath, fileName) but the second parameter expects a MIME type, not a filename. This caused the filename to be stored as ContentType. ### Description of Change <!-- Enter description of the fix in this section --> Fixed FileResult initialization to properly preserve the filename and ContentType. ### Regarding Test Case Picking an image is not possible in a test. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33348 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [ ] Android - [ ] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **iOS**<br> <video src="https://github.com/user-attachments/assets/47360519-a071-47eb-9a79-66069f8711a8" width="300" height="600"> | **iOS**<br> <video src="https://github.com/user-attachments/assets/47a43e9d-c90f-4c79-ac81-779e50198cff" width="300" height="600"> |
…stroyed activities (#29780) ## Problem Random crashes occurring on Android devices with the error: ``` java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity at com.bumptech.glide.manager.RequestManagerRetriever.assertNotDestroyed(RequestManagerRetriever.java:236) at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:110) at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:92) at com.bumptech.glide.Glide.with(Glide.java:545) at com.microsoft.maui.glide.MauiCustomTarget.lambda$clear$0$com-microsoft-maui-glide-MauiCustomTarget(MauiCustomTarget.java:88) ``` This happens when Glide attempts to clear image targets using a Context whose underlying Activity has been destroyed. ## Solution Added defensive context destruction check in `MauiCustomTarget.clear()` before calling `Glide.with(context).clear(this)`. **Key Changes:** 1. **Added private context lifecycle validation methods to MauiCustomTarget:** - `isContextDestroyed()` - Checks if context/activity is destroyed or finishing - `getActivity()` - Safely extracts Activity from Context (handles ContextWrapper chains) 2. **Protected MauiCustomTarget.clear() operation:** - Added context check before calling `Glide.with(context).clear(this)` - Includes verbose logging when the clear operation is skipped due to destroyed context **Behavior:** - When context is destroyed, `clear()` returns early without attempting to call Glide - Matches Glide's own validation logic: `activity.isFinishing() || activity.isDestroyed()` - Logs a debug message when clear is skipped (if verbose logging is enabled) **Example of the fix:** ```java private void clear() { post(() -> { if (isContextDestroyed(context)) { if (logger.isVerboseLoggable) { logger.v("clear() skipped - context destroyed: " + resourceLogIdentifier); } return; } Glide .with(context) .clear(this); }); } ``` This is a surgical, minimal fix that targets the specific crash location identified in the stack trace while maintaining all existing functionality. Fixes #29699. --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more <a href="https://gh.io/copilot-coding-agent-tips">Copilot coding agent tips</a> in the docs. <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/dotnet/maui/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jfversluis <939291+jfversluis@users.noreply.github.com> Co-authored-by: jonathanpeppers <840039+jonathanpeppers@users.noreply.github.com>
…33406) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Root Cause : Navigation fails because `UISearchController` was dismissed before `ItemSelected` was called, triggering a UIKit transition that deactivates the Shell navigation context and prevents the navigation from completing ### Description of Change : Changed the order in `OnSearchItemSelected` in `ShellPageRendererTracker.cs` to call `ItemSelected` before deactivating the search controller for correct event handling. <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #33356 ### Tested the behavior in the following platforms - [x] Windows - [x] Android - [x] iOS - [x] Mac | Before Issue Fix | After Issue Fix | |----------|----------| | <video src="https://github.com/user-attachments/assets/0e63dd86-1965-404a-8d07-6d3afd952498"> | <video src="https://github.com/user-attachments/assets/af867272-434f-411e-9a6f-a68a87cfc3a7"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> --------- Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
### Issue Description: VoiceOver does not read the ComboBox State correctly, In the sample, the ComboBox behavior is implemented using SfTextInputLayout with a Picker. However, I have already implemented the semantic properties for picker , it was overriden by SfTextInputLayout, the expectation is for VoiceOver to recognise and announce it as a ComboBox state. ### Description of change : Update SemanticProperties using property changed on IsOpen property in picker to achieve the expected output. > Note: net9.0 PR - dotnet/maui-samples#651 ### Issues Fixed Fixes [#30899 ](#30899) ### Tested the behaviour in the following platforms - [ ] Android - [ ] Windows - [ ] iOS - [x] Mac
…e - 1 (#33602) This PR addresses the UI test image failures that occurred in the inflight/candidate branch #33574 and includes updates to improve rendering and test stability across platforms. - Resaved snapshots for these test cases due to this PR fix #33281: CanvasShouldHonorBlur, VerifyScrollViewWithScrollToPositionCenterAndGridContent, VerifyScrollViewWithRTLAndGridContent, VerifyScrollViewWithScrollToPositionEndAndGridContent, VerifyScrollViewWithScrollToPositionMakeVisibleAndGridContent, VerifyScrollViewWithScrollToPositionStartAndGridContent, DownSizeImageAppearProperly, Issue30440ImageShouldClipCorrectly, IndicatorViewWithTemplatedIcon, VerifyCarouselLayoutOrientationChange, VerifyCarouselViewItemsSourceClearedDynamically, EmptyViewShouldDisplayWhenCollectionViewIsInsideVerticalStackLayout. - Issue18751Test - Added the failing condition for Android due to the image not loading on CI. Already restricted for other platforms; now it fails on Android as well. - Issue18751Test - Added the failing condition for Windows due to AutomationId not working on layout in Appium. - VariousSpanGesturePermutation - Increased the tap coordinates due to this PR fix #33281 changes. --------- Co-authored-by: sheiksyedm <sheiksyedm@syncfusion.com> # Conflicts: # src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18751.cs
ef891bc to
7d6e70b
Compare
|
/azp run maui-pr-uitests, maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
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 [Android] Implement material3 support for CheckBox #33339
🔧 Fixes
CollectionView
🔧 Fixes
Essentials
[Windows]Fix NullReferenceException in OpenReadAsync for FileResult created with full path by @devanathan-vaithiyanathan in [Windows]Fix NullReferenceException in OpenReadAsync for FileResult created with full path #28238
🔧 Fixes
Image
Fix Glide IllegalArgumentException in MauiCustomTarget.clear() for destroyed activities by @jfversluis via @copilot in Fix Glide IllegalArgumentException in MauiCustomTarget.clear() for destroyed activities #29780
🔧 Fixes
Label
[Android] Fix for Label WordWrap width issue causing HorizontalOptions misalignment by @praveenkumarkarunanithi in [Android] Fix for Label WordWrap width issue causing HorizontalOptions misalignment #33281
🔧 Fixes
Fix to Improve Flyout Accessibility by Adjusting UITableViewController Labels by @SuthiYuvaraj in Fix to Improve Flyout Accessibility by Adjusting UITableViewController Labels #31619
🔧 Fixes
Mediapicker
[Regression][iOS] Fix MediaPicker PickPhotosAsync getting file name in contentType property by @devanathan-vaithiyanathan in [Regression][iOS] Fix MediaPicker PickPhotosAsync getting file name in contentType property #33390
🔧 Fixes
Navigation
Fix handler not disconnected when removing non visible pages using RemovePage() by @Vignesh-SF3580 in Fix handler not disconnected when removing non visible pages using RemovePage() #32289
🔧 Fixes
Picker
[Android] Fix Picker IsOpen not reset when picker is dismissed by @devanathan-vaithiyanathan in [Android] Fix Picker IsOpen not reset when picker is dismissed #33332
🔧 Fixes
Shell
[iOS & Catalyst ] Fixed IsEnabled property should work on Tabs by @SubhikshaSf4851 in [iOS & Catalyst ] Fixed IsEnabled property should work on Tabs #33369
🔧 Fixes
[iOS,Windows] Fix navigation bar colors not resetting when switching ShellContent by @Vignesh-SF3580 in [iOS,Windows] Fix navigation bar colors not resetting when switching ShellContent #33228
🔧 Fixes
[iOS] Fixed Shell navigation on search handler suggestion selection by @SubhikshaSf4851 in [iOS] Fixed Shell navigation on search handler suggestion selection #33406
🔧 Fixes
Templates
Xaml
[XSG][BindingSourceGen] Add support for CommunityToolkit.Mvvm ObservablePropertyAttribute by @simonrozsival via @copilot in [XSG][BindingSourceGen] Add support for CommunityToolkit.Mvvm ObservablePropertyAttribute #33028
🔧 Fixes
📦 Other (2)