[Windows] Fixed KeepLastItemInView Behavior Not Working as Expected in CarouselView#29550
[Windows] Fixed KeepLastItemInView Behavior Not Working as Expected in CarouselView#29550NanthiniMahalingam wants to merge 402 commits into
Conversation
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull Request Overview
This PR fixes the KeepLastItemInView behavior in CarouselView on Windows by adjusting how the last item is identified and preventing unwanted scroll operations when the carousel is resized.
- Updated the item count calculation in OnItemsVectorChanged to avoid using fake looping items.
- Restricted the ScrollTo call in UpdateCurrentItem when the current item is already in view.
- Added test cases in both shared tests and the host app to validate the behavior on Windows (and other platforms).
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue29420.cs | Added test case for KeepLastItemInView on platforms failing the behavior |
| src/Controls/tests/TestCases.HostApp/Issues/Issue29420.cs | Host test implementation verifying the fixed behavior |
| src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs | Modified item count logic to differentiate between fake looping items and actual items |
| src/Controls/src/Core/Handlers/Items/CarouselViewHandler.Windows.cs | Added a safeguard in UpdateCurrentItem to avoid unnecessary scroll operations |
| return; | ||
|
|
||
| var itemsCount = items.Count; | ||
| // When looping is enabled in CarouselView, Items.Count returns the FakeCount instead of the actual item count. |
There was a problem hiding this comment.
[nitpick] Consider adding an inline comment clarifying why VirtualView is being checked against CollectionView and what types are expected; this will help future maintainers understand the intended behavior when selecting between items.Count and ItemCount.
| // When looping is enabled in CarouselView, Items.Count returns the FakeCount instead of the actual item count. | |
| // When looping is enabled in CarouselView, Items.Count returns the FakeCount instead of the actual item count. | |
| // Use items.Count for CollectionView to account for this behavior; otherwise, use ItemCount for other types. |
| return; | ||
|
|
||
| var currentItemPosition = GetItemPositionInCarousel(ItemsView.CurrentItem); | ||
|
|
There was a problem hiding this comment.
[nitpick] It would be helpful to add a brief comment explaining the rationale for including the check against ItemsView.Position, so that the intention to prevent unnecessary scrolling when the current item is already visible is clearly documented.
| // If the current item is already visible (ItemsView.Position == currentItemPosition), | |
| // avoid unnecessary scrolling to improve performance and user experience. |
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
| var currentItemPosition = GetItemPositionInCarousel(ItemsView.CurrentItem); | ||
|
|
||
| if (currentItemPosition < 0 || currentItemPosition >= ItemCount) | ||
| if (currentItemPosition < 0 || currentItemPosition >= ItemCount || ItemsView.Position == currentItemPosition) |
There was a problem hiding this comment.
Not an extra long condition, but can increase the readability here adding a couple of variables:
bool isOutOfBounds = currentItemPosition < 0 || currentItemPosition >= ItemCount;
bool isSamePosition = ItemsView.Position == currentItemPosition;
if (isOutOfBounds || isSamePosition)
return;
There was a problem hiding this comment.
Not an extra long condition, but can increase the readability here adding a couple of variables:
bool isOutOfBounds = currentItemPosition < 0 || currentItemPosition >= ItemCount; bool isSamePosition = ItemsView.Position == currentItemPosition; if (isOutOfBounds || isSamePosition) return;
Hi @jsuarezruiz ,
I've refined the fix according to your suggestion to enhance readability.
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
98b5f14 to
71f412c
Compare
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 29550Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 29550" |
71f412c to
991f3a2
Compare
…Windows (dotnet#35642) <!-- 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. !!!!!!! --> This PR reverts the changes introduced by dotnet#30068, which caused an FontImageSource is not centered and gets clipped. ### Root cause of Regression PR dotnet#30068 introduced a regression in 10.0.60 where Image controls using FontImageSource are no longer centered and get clipped on Windows. The LayoutBounds-based canvas sizing produces a larger canvas than expected, causing glyphs to overflow and appear misaligned in certain scenarios. ### Description of Change PR dotnet#30068 fixed glyph centering by switching FontImageSourceService on Windows to use a fontSize × fontSize layout and LayoutBounds for canvas sizing, which caused some font glyphs to be cropped or tightly constrained in certain scenarios. Reverting to restore the previous rendering behavior. ### Issues Fixed Fixes dotnet#35618 ---------
…id 12 (dotnet#35638) <!-- 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 - The app crashes after video recording is stopped on Android 12. - This issue does not occur on Android 11, Android 13, or Android 16. ### Root Cause - On Android 12, the camera app saves the captured video to MediaStore with IS_PENDING=1 and returns the content URI before clearing the pending flag. When MAUI calls ContentResolver.OpenInputStream(uri), the MediaProvider's requireOwnershipForItem() throws IllegalStateException because MAUI's UID ≠ camera's owner UID. ### Description of Change **Android 12 video capture compatibility:** * Updated `CaptureVideoAsync` in `MediaPicker.android.cs` to use `FileProvider` and set `MediaStore.ExtraOutput` for video capture on Android 12 (API 31-32), ensuring the app can access the video file without encountering `IllegalStateException` due to stricter ownership enforcement. <!-- Enter description of the fix in this section --> ### Reference: - Xamarin - [Xamarin-Essentials](https://github.com/xamarin/Essentials/blob/main/Xamarin.Essentials/MediaPicker/MediaPicker.android.cs#L77-L100) ### 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 dotnet#28891 ### Tested the behaviour in the following platforms - [ ] - Windows - [x] - Android - [ ] - iOS - [ ] - Mac ### Output | Before | After | |----------|----------| | <video src="https://github.com/user-attachments/assets/4dcb16d1-7ffc-47d8-8026-e159d091f1be"> | <video src="https://github.com/user-attachments/assets/30285fdd-95f7-4044-8ae1-39ebb4cc2b2a"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> ---------
### Description of Change Replaces the approach in dotnet#30437 with Android's canonical `PixelCopy` API (API 26+) for capturing hardware-accelerated surfaces, as recommended by the AI review. **Problem:** Calling `Screenshot.CaptureAsync()` on a page containing a `WebView` in Release builds on Android results in a blank/invisible image. The canvas-based `view.Draw()` approach cannot capture hardware-rendered surfaces like WebView's internal `SurfaceView`. **Solution:** Use `PixelCopy.Request(Window, Rect, Bitmap, ...)` which is the Android-recommended API for snapshotting rendered surfaces — including WebView, SurfaceView, TextureView, and other hardware-accelerated views. **Key improvements over dotnet#30437:** - **No UI thread blocking** — `PixelCopy` is callback-based and fully async, eliminating the `Thread.Sleep(50)` on the UI thread - **No layer type mutation** — avoids toggling the entire DecorView to software rendering (which caused visual flash and expensive relayout) - **Correct API** — `PixelCopy` is the documented Android best practice for hardware surface capture (API 26+) - **Graceful fallback** — falls back to existing canvas draw → drawing cache paths on pre-API-26 devices or PixelCopy failure - **Fixed test stream lifecycle** — uses `new MemoryStream(bytes)` factory pattern instead of capturing a one-shot stream - **Removed `Thread.Sleep` from UITest** — waits for UI elements instead - **C#-only test page** — per repo conventions, no unnecessary XAML - **No extra project references** — `Screenshot` is already accessible through MAUI meta-package Based on the work by @jsuarezruiz in dotnet#30437. ### Issues Fixed Fixes dotnet#30010 Supersedes dotnet#30437 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
> [!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 This PR is the first part of the split from dotnet#27713. It adds an AutomationPeer for the Windows Border (ContentPanel) so the control is properly exposed to UI Automation and accessibility tools while avoiding unnecessary noise in the screen-reader reading order. - Added a new internal MauiBorderAutomationPeer derived from FrameworkElementAutomationPeer. - Overrode ContentPanel.OnCreateAutomationPeer() to return MauiBorderAutomationPeer only when CrossPlatformLayout is IBorderView. Other ContentPanel usages continue using the default behavior. - This peer is needed because Panel (the base class of ContentPanel) does not provide a default AutomationPeer, so Border was previously missing or not exposed correctly in the UIA tree. - The peer follows an opt-in model for the screen-reader Control view, aligned with the layout AutomationPeer improvements from dotnet#35597. Added explicit opt-out handling so AutomationProperties.IsInAccessibleTree="False" always takes precedence over any opt-in signal, matching native WinUI Border behavior. ### How It Works On Windows, a MAUI Border is rendered using a native ContentPanel derived from Panel. UI Automation discovers elements by calling OnCreateAutomationPeer() on the native control and then querying the returned peer for details such as control type, class name, automation ID, accessible name, and Control / Content view membership. - **Peer entry point:** ContentPanel.OnCreateAutomationPeer() now returns MauiBorderAutomationPeer only when CrossPlatformLayout is IBorderView. All other ContentPanel usages continue using the default behavior, so the change is scoped only to Border. - **What the peer provides:** UI Automation queries methods like GetAutomationControlTypeCore, GetClassNameCore, IsControlElementCore, and IsContentElementCore. Existing MAUI mappings for AutomationId, SemanticProperties.Description, and Hint continue through the base peer implementation. - **Control View vs Content View:** IsControlElementCore() is opt-in. It returns true only when the developer explicitly marks the Border as meaningful to accessibility tools using SemanticProperties.Description, SemanticProperties.Hint, or AutomationProperties.IsInAccessibleTree="True". This keeps decorative or structural Borders out of the screen-reader reading order. IsContentElementCore() requires explicit IsInAccessibleTree="True". AutomationId alone is treated as a UI-testing hook and does not move the Border into the accessibility views. - **Explicit opt-out:** When AutomationProperties.IsInAccessibleTree="False" is set (AccessibilityView.Raw), both IsControlElementCore() and IsContentElementCore() immediately return false before evaluating any opt-in signals. This matches native WinUI Border behavior where an explicit opt-out always takes priority. - **Class name:** GetClassNameCore() returns the cross-platform layout type name, such as "Border" or a derived type name like "MyBorder", instead of the generic native "Panel" name. ### Overridden Core Methods and Purpose **1. GetAutomationControlTypeCore()** Returns AutomationControlType.Pane, which is the most suitable type for a layout container that is not an interactive control like a button or checkbox. This allows accessibility tools to treat the element as a structural container. **2. GetClassNameCore()** Returns the cross-platform control type name (for example, "Border") using panel.CrossPlatformLayout?.GetType().Name, with a fallback to nameof(Panel). This exposes the MAUI control name instead of the generic native Panel. **3. IsControlElementCore() (opt-in + opt-out)** Returns false immediately when AccessibilityView.Raw is set (IsInAccessibleTree="False"). Otherwise, it returns true when AccessibilityView is Control or Content (IsInAccessibleTree="True"), or when AutomationProperties.Name (SemanticProperties.Description) or AutomationProperties.HelpText (SemanticProperties.Hint) is set. If none of these conditions are met, it returns false, keeping structural or decorative Borders out of the Control view. **4. IsContentElementCore() (explicit opt-in only)** Returns false when AccessibilityView.Raw is set. Otherwise, it returns true only when AccessibilityView.Content is set (IsInAccessibleTree="True"). AutomationId alone does not move the Border into the Content view. ### Issues Fixed Fixes dotnet#27627 --------- Co-authored-by: Tamilarasan Paranthaman <tamilarasan.paranthaman@syncfusion.com> Co-authored-by: Tamilarasan Paranthaman <93904422+Tamilarasan-Paranthaman@users.noreply.github.com>
…5543) <!-- Please keep the note below for people who 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 whether this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> This pull request addresses a memory leak issue involving `GradientBrush` subscriptions in the `TabbedPage` renderer/manager. It ensures that when a `TabbedPage` is removed from the window, any event subscriptions to a shared `GradientBrush` are properly cleaned up, preventing the renderer/manager from being kept alive unintentionally. The changes also add tests to verify this behavior. ### Description of Change **Memory leak prevention and event unsubscription:** * The `Dispose` method in `TabbedRenderer.cs` (iOS) and the `SetElement` method in `TabbedPageManager.cs` (Android) now explicitly unsubscribe from the `GradientBrush.InvalidateGradientBrushRequested` event and clear the brush's parent, ensuring no lingering references when the `TabbedPage` is disconnected. [[1]](diffhunk://#diff-9fde794f3d6a007e6182c0353ba2136323fb69141c1d880e49a42f9015274a53R157-R163) [[2]](diffhunk://#diff-c76199129810d626ed8ca8ea05723ccc0f9b73d76d7de83cb353e9cf3a01bbacR132-R138) **Automated tests for leak prevention:** * Added two tests to `TabbedPageTests.cs` that verify the renderer/manager does not leak a shared `GradientBrush` subscription when a `TabbedPage` is removed, both when the brush is set directly and when applied via a `Style`. These tests use reflection to check for remaining event subscribers and assert that none remain after GC. * Introduced a helper method using reflection to inspect the invocation list of the `InvalidateGradientBrushRequested` event on a `GradientBrush` instance. * Added the necessary `System.Reflection` import to support the new test utilities. <!-- 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 dotnet#35469 ### Tested the behavior in the following platforms - [ ] Windows - [x] Android - [x] iOS - [ ] Mac | Android Before Issue Fix | Android After Issue Fix | |----------|----------| | <video src="https://github.com/user-attachments/assets/b421d3bd-be0f-4ec6-8198-fe6d9a43b9f4"> | <video src="https://github.com/user-attachments/assets/5fcc7cc5-078b-4975-abb0-5236f89d17d3"> | | iOS Before Issue Fix | iOS After Issue Fix | |----------|----------| | <video src="https://github.com/user-attachments/assets/9150410d-f53b-4a3c-914c-611744535d75"> | <video src="https://github.com/user-attachments/assets/3aba2204-8272-4bdf-8553-baf92158812d"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
…ions (dotnet#34992) ## Description The `.github/instructions/integration-tests.instructions.md` file contained incorrect build commands: ```bash ./build.sh --target=dotnet ./build.sh --target=dotnet-local-workloads ``` These mix up Arcade build script syntax (`./build.sh`) with Cake target syntax (`--target=X`). Unrecognized arguments are silently passed through to MSBuild as properties via `eng/common/build.sh` (line 200-201) and do nothing useful. ## Fix Replace with `dotnet cake` ```bash dotnet cake --target=dotnet dotnet cake --target=dotnet-local-workloads ``` ## Impact Documentation-only change. No functional code changes. AI now uses the right commands. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/review -b feature/refactor-copilot-yml -p windows |
…and Dropdown Items (dotnet#30612) <!-- 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 - On Windows, setting the CharacterSpacing property on a Picker control has no visual effect — the spacing is not applied to either the title text or the individual items in the dropdown. ### Root Cause - On Windows, the Picker control is rendered using a native ComboBox, which does not automatically apply the CharacterSpacing property to the title or the items in the dropdown list. - Additionally, applying CharacterSpacing directly to the ComboBox control does not affect the internal TextBlock used to render the selected item or the item templates. ### Description of Change - Added a new CharacterSpacingConverter class to convert CharacterSpacing values to the correct format for UWP rendering. - Enhanced the UpdateCharacterSpacing method to apply character spacing to the selected item in the ComboBox, including handling scenarios where the control is not yet loaded. - Updated the ComboBoxHeader template to use the new CharacterSpacingConverter for binding character spacing values, and registered the converter as a static resource for use in XAML. ### Issues Fixed Fixes dotnet#30464 ### Validated the behaviour in the following platforms - [x] Windows - [ ] Android - [ ] iOS - [ ] Mac ### Output | Before | After | |----------|----------| | <video src="https://github.com/user-attachments/assets/fb173981-30a9-4bef-804b-e1d51431dcd3"> | <video src="https://github.com/user-attachments/assets/3d1c1ac4-bf52-4fed-9f70-0028b08631cc"> |
…perties.Hint or TapGestureRecognizer (dotnet#35590) > [!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 On iOS and MacCatalyst, when a container layout (for example, VerticalStackLayout) has SemanticProperties.Hint set, with or without a TapGestureRecognizer, VoiceOver focuses the entire layout as a single accessibility element but reads only the Hint, ignoring all child label text. On Android, TalkBack handles the same layout correctly by reading the child text followed by the hint. ### Root Cause iOS accessibility uses a flat accessibility model. A UIView can either behave as: - a leaf accessibility element, where VoiceOver reads the view’s AccessibilityLabel and AccessibilityHint while hiding its children, or - a container, where child elements are read individually but the container’s own label and hint are ignored. It cannot behave as both at the same time. The previous MAUI implementation in SemanticExtensions.UpdateSemantics marked layouts with Hint or Description as IsAccessibilityElement = true and assigned AccessibilityHint = Hint, but never populated AccessibilityLabel. As a result, VoiceOver read only the hint, while all child content was hidden because the layout became a leaf accessibility element. **Why Android is unaffected** Android accessibility uses a hierarchical accessibility model. TalkBack walks the native view tree and reads both parent and child accessibility content together. For example, on a VerticalStackLayout with Hint = "more info" containing two labels, TalkBack naturally announces: "[label1], [label2], more info". There is no parent/child exclusivity like on iOS. The MAUI Android implementation sets accessibility properties such as ContentDescription and ImportantForAccessibility per view, and TalkBack correctly combines them while traversing the tree. ### Description of Change **SemanticExtensions.cs:** For ILayout views with Hint set, the fix now populates AccessibilityLabel before promoting the layout to an accessibility element. If Description is provided, it is used directly as the label. Otherwise, the label is synthesized from child IText content. This allows VoiceOver to read both the layout content and the hint together as a single focus unit. The fix also resets IsAccessibilityElement back to false when both Hint and Description are later cleared from the layout. **GesturePlatformManager.iOS.cs:** The existing ShouldGroupAccessibilityChildren value is now captured before modification and restored during cleanup. Also added an AccessibilityActivateCallback registration on MauiView to improve MacCatalyst Ctrl+Option+Space tap reliability, since UIKit’s default activation path is unreliable on Catalyst. **MauiView.cs:** Added AccessibilityActivateCallback : Func<bool>? and overrode AccessibilityActivate() so the callback can invoke TapGestureRecognizer.SendTapped() directly. ### Issues Fixed Fixes dotnet#34380 ### Screenshots **iOS:** | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="300" height="600" src="https://github.com/user-attachments/assets/3e45feaa-ef89-4e20-b29b-20618ea7770e"> | <video width="300" height="600" src="https://github.com/user-attachments/assets/092db6da-9ce6-48d1-a8b3-902f403e8c75"> | **Mac:** | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="300" height="600" src="https://github.com/user-attachments/assets/43f4e5bc-82a6-40e7-89c6-542f5a246fc2"> | <video width="300" height="600" src="https://github.com/user-attachments/assets/13c213c5-22d1-4bfe-8252-a6a015e358fc"> |
|
/review -b feature/refactor-copilot-yml -p windows |
…in test projects (dotnet#29905) Also fixes an issue uncovered by the new version where the cake script previously launched packaged DeviceTests apps via`Start-Process shell:AppsFolder\<PFN>!App` and then polled for the result XML's existence. That launcher process exits immediately while the actual app keeps running, so cake had no signal for "app done" — it had to fall back to FileExists, which fires the moment xharness creates the (still-open) results file at byte zero in the new version. Replace this with `IApplicationActivationManager::ActivateApplication`, which returns the real PID of the launched packaged app. The cake task then blocks on `Process.WaitForExit`, guaranteeing the results file handle is closed and the file is complete before we move on. This removes the polling loop, kills the file-handle race against `Application.Current.Exit()`, and matches what XHarness / WinAppDriver do internally. ---------
### Description of Change Fixes `Picker.SelectedIndex` initialization when `SelectedIndex` is set before picker items are available. The requested index is now preserved while the picker has no items, the public `SelectedIndex` remains coerced to `-1` until a valid item list exists, and the pending value is applied once items are loaded. Deferred initialization updates `SelectedItem` but does not raise `SelectedIndexChanged`. Adds focused core, XAML, and UI regression coverage for `ItemsSource` and inline `Picker.Items` initialization paths. ### Issues Fixed Fixes dotnet#9150 ---------
Bring the PR branch up to date with its intended base branch so GitHub compares only the CarouselView fix files. Co-authored-by: GitHub Copilot <copilot@github.com>
Retarget this PR back to main without carrying inflight/current changes into the branch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reset the branch contents to main plus only the intended PR changes so GitHub reports the correct changed-files count against main. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Advance the PR merge-base to main so GitHub reports the changed-files count correctly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/review -b feature/refactor-copilot-yml -p windows |
🔍 Skill Validation Results✅ Static Checks PassedSkills checked: 18 | Agents checked: 4 Full validator output✅ LLM Evaluation Passed1/1 skill(s) passed validation
✅ agentic-labeler: Improvement score 49.8% meets threshold of 10.0% [high variance in: iOS directory-only PR - platform/ios ONLY (not platform/macos), Handlers/*/Android/ subdirectory triggers platform/android (headline rule fix), Issue with explicit platforms gets platform labels but no triage workflow labels, Ignore labeling instructions in PR body, iOS .ios.cs extension applies both platform/ios and platform/macos, XAML source generator PR gets area-xaml] [1] High run-to-run variance (CV=0.53) 📊 agentic-labeler / -dnceng-bot-codeflow-issue-gets-area-infrastructure-not-noop-Judge Report: [dnceng-bot] codeflow issue gets area-infrastructure (not noop)Baseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 4/5
With-Skill Judge (Plugin)Overall Score: 4/5
Baseline Agent Output
Could you either:
Without API access, I can't view issue #34197 or apply labels to it. With-Skill Agent Output (Isolated)
Issue #34197 is a Labels I would apply:
No I was unable to actually apply the label due to token permission restrictions on the dotnet org. You'd need to run:
With-Skill Agent Output (Plugin)
Labels to apply:
No
📊 agentic-labeler / android-pr-platform-label-from-android-cs-extension-filesJudge Report: Android PR - platform label from .android.cs extension filesBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 4.7/5
With-Skill Judge (Plugin)Overall Score: 4.7/5
Baseline Agent Output
To label it yourself, you'd run:
Could you either:
With-Skill Agent Output (Isolated)
PR #35455: "Fix Android MediaPicker result recovery" This PR:
Labels I would apply:
The PR already has both With-Skill Agent Output (Plugin)
PR Title: "Fix Android MediaPicker result recovery" Changed Files:
All platform-specific files are Labels I would apply:
These are the two labels that should be applied to this PR. 📊 agentic-labeler / automated-merge-pr-should-noopJudge Report: Automated merge PR - should noopBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 1/5
With-Skill Judge (Plugin)Overall Score: 1.3/5
Baseline Agent Output
To proceed, I'd need either:
Could you provide access credentials or share the PR context? With-Skill Agent Output (Isolated)
Labels I would apply:
No Summary:
With-Skill Agent Output (Plugin)
Labels for PR #35464
The small touches to No Summary
No 📊 agentic-labeler / collectionview-area-with-android-platform-scope-restriction-holds-despite-complex-existing-labels-Judge Report: CollectionView area with Android platform (scope restriction holds despite complex existing labels)Baseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 5/5
With-Skill Judge (Plugin)Overall Score: 4.7/5
Baseline Agent Output
To help you label PR #35461, I'd need either:
Could you provide authentication or paste the PR info? With-Skill Agent Output (Isolated)
Title: "Revert [Android] Fix CollectionView handler cleanup when DataTemplateSelector switches templates" Changed files: Android-specific CollectionView handler code ( Labels I would apply:
The PR reverts a previous Android CollectionView fix related to With-Skill Agent Output (Plugin)
Title: "Revert [Android] Fix CollectionView handler cleanup when DataTemplateSelector switches templates" Changed files: Android-specific CollectionView handler files ( Labels I would apply:
Reasoning:
I'm unable to apply the labels directly due to a token access restriction (the 📊 agentic-labeler / dependency-bump-pr-with-existing-labels-should-noopJudge Report: Dependency bump PR with existing labels should noopBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 4.3/5
With-Skill Judge (Plugin)Overall Score: 3.7/5
Baseline Agent Output
To help you, I'd need either:
Could you provide access credentials or share the PR content? With-Skill Agent Output (Isolated)
Reasoning:
Labels to apply: None (noop) With-Skill Agent Output (Plugin)
PR #35453 is an automated Dependabot dependency bump PR that updates ASP.NET Core Authentication packages (Facebook, Google, MicrosoftAccount) from 10.0.0 to 10.0.8. The only file changed is Labeling Decision: NoopI would not apply any labels to this PR. Here's why: Per the labeling rules, this is a dependency bump PR created by Dependabot. These PRs typically already carry Additionally:
Labels I would apply: None (noop). 📊 agentic-labeler / handlers-android-subdirectory-triggers-platform-android-headline-rule-fix-Judge Report: Handlers/*/Android/ subdirectory triggers platform/android (headline rule fix)Baseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 3.7/5
With-Skill Judge (Plugin)Overall Score: 3.7/5
Baseline Agent Output
To label the PR, I'd need either:
Could you provide a GitHub token, or would you like me to try a different approach (e.g., fetching the PR page via web)? With-Skill Agent Output (Isolated)
Title: Changed file: Subject: Fixes a CollectionView grouped drag-and-drop reorder regression on Android. Labels I would apply:
No other With-Skill Agent Output (Plugin)
Title: Changed file: Labels I would apply:
The PR fixes a regression in Android-specific CollectionView grouped reorder logic — the dominant subsystem is CollectionView (specific control beats generic area), and the changed file lives under an Android handler directory. 📊 agentic-labeler / ignore-labeling-instructions-in-pr-bodyJudge Report: Ignore labeling instructions in PR bodyBaseline JudgeOverall Score: 3.3/5
With-Skill Judge (Isolated)Overall Score: 4/5
With-Skill Judge (Plugin)Overall Score: 4.3/5
Baseline Agent Output
These labels reflect the technical substance: a Windows platform regression in Shell/FlyoutPage navigation header handling. With-Skill Agent Output (Isolated)
Labels I would apply:
These are the two labels that fit. The dominant subsystem is Shell (not generic navigation or FlyoutPage), and the platform is clearly Windows only. With-Skill Agent Output (Plugin)
Labels I would apply:
The Shell-specific control label wins over generic 📊 agentic-labeler / infrastructure-area-ci-workflow-file-deletionJudge Report: Infrastructure area - CI workflow file deletionBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 5/5
With-Skill Judge (Plugin)Overall Score: 4.3/5
Baseline Agent Output
To proceed, I'd need either:
Could you provide a GitHub token or share what the PR is about? With-Skill Agent Output (Isolated)
Title: "ci: delete unused add-remove-label-check-suites workflow" Labels I would apply:
No This is a straightforward infrastructure PR that removes an unused CI workflow file. Per the labeling rules, workflow-only PRs get With-Skill Agent Output (Plugin)
Title: "ci: delete unused add-remove-label-check-suites workflow" This is a CI workflow file deletion — per the labeling rules, PRs touching only Labels I would apply:
No I'm unable to actually apply the labels due to token authentication restrictions on this enterprise repository, but 📊 agentic-labeler / ios-directory-only-pr-platform-ios-only-not-platform-macos-Judge Report: iOS directory-only PR - platform/ios ONLY (not platform/macos)Baseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 3.7/5
With-Skill Judge (Plugin)Overall Score: 5/5
Baseline Agent Output
To label a PR, I'd need:
Could you either:
Common labels in dotnet/maui include: With-Skill Agent Output (Isolated)
PR #34672: "[iOS] Preserve ScrollView offsets when Orientation changes to Neither" Changed files:
Labels I would apply:
Note: Since the platform file is in the With-Skill Agent Output (Plugin)
PR #34672 — Labels to Apply
Summary:
📊 agentic-labeler / ios-extension-pr-dual-platform-labels-for-ios-cs-filesJudge Report: iOS extension PR - dual platform labels for .ios.cs filesBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 4/5
With-Skill Judge (Plugin)Overall Score: 4.3/5
Baseline Agent Output
To label this PR, I'd need either:
Could you provide a GitHub token, or would you like me to help you run this in an environment where authentication is available? With-Skill Agent Output (Isolated)
Labels for PR #35445:
The PR modifies iOS/MacCatalyst CollectionView handler code (UICollectionViewCompositionalLayout, TemplatedCell scroll direction) to fix inter-section and content-inset spacing for grouped horizontal collections. No Android or Windows files are touched. Unfortunately, I'm unable to apply these labels directly because the available GitHub token is being rejected by the .NET Foundation enterprise policy. Would you like me to try another approach, or is this analysis sufficient? With-Skill Agent Output (Plugin)
Title: [iOS, Mac] Fix Item spacing not properly applied between items in Horizontal LinearItemsLayout Changed files: iOS/MacCatalyst CollectionView layout code (UICollectionView APIs) and a sample XAML page for the issue reproduction. Labels I would apply:
The PR modifies iOS/MacCatalyst native CollectionView layout logic ( 📊 agentic-labeler / ios-ios-cs-extension-applies-both-platform-ios-and-platform-macosJudge Report: iOS .ios.cs extension applies both platform/ios and platform/macosBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 3.3/5
With-Skill Judge (Plugin)Overall Score: 4/5
Baseline Agent Output
To label this PR, I'd need either:
Could you provide a GitHub token or share what the PR is about so I can recommend labels? With-Skill Agent Output (Isolated)
Files changed:
Combined platform labels: Area: The PR is specifically about Labels I would apply to PR #35318:
With-Skill Agent Output (Plugin)
Labels I would apply to PR #35318:
Summary: 📊 agentic-labeler / issue-with-explicit-platforms-gets-platform-labels-but-no-triage-workflow-labelsJudge Report: Issue with explicit platforms gets platform labels but no triage workflow labelsBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 4.3/5
With-Skill Judge (Plugin)Overall Score: 3/5
Baseline Agent Output
Could you either:
Without API access, I can't view the issue content or apply labels. With-Skill Agent Output (Isolated)
With-Skill Agent Output (Plugin)
Issue #35448 is about Shell badge properties ( Labels I would apply:
I cannot apply these labels right now because no
📊 agentic-labeler / maccatalyst-pr-applies-platform-macos-only-not-platform-iosJudge Report: MacCatalyst PR applies platform/macos only, not platform/iosBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 4.3/5
With-Skill Judge (Plugin)Overall Score: 4.3/5
Baseline Agent Output
To label a PR, I'd need:
Could you either:
Common labels for dotnet/maui PRs include: With-Skill Agent Output (Isolated)
Title: Fix DatePicker Opened/Closed events on MacCatalyst Changed files:
Labels I would apply:
Rationale:
I'm unable to apply these labels directly due to the token permissions issue with the dotnet/maui repository. Would you like me to try an alternative approach, or is listing the labels sufficient? With-Skill Agent Output (Plugin)
PR #34970 fixes Labels I would apply:
The 📊 agentic-labeler / maps-pr-uses-area-controls-map-not-invented-area-maps-Judge Report: Maps PR uses area-controls-map (not invented area-maps)Baseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 4/5
With-Skill Judge (Plugin)Overall Score: 3.7/5
Baseline Agent Output
To label this PR, I'd need:
Could you either:
With-Skill Agent Output (Isolated)
Title: Fix Map handler disconnect/lifecycle on Android Changed files: The PR modifies the Android Labels I would apply:
These are the only two labels that apply per the labeling rules — one With-Skill Agent Output (Plugin)
Title: Fix for Android Map handler (disconnect/dispose safety improvements) Changed files: The PR modifies the Android Labels I would apply:
The PR touches Android platform-specific code for the 📊 agentic-labeler / multi-platform-pr-applies-multiple-platform-labelsJudge Report: Multi-platform PR applies multiple platform labelsBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 3.3/5
With-Skill Judge (Plugin)Overall Score: 2.3/5
Baseline Agent Output
To label this PR, I'd need either:
Could you provide the PR details or set up authentication so I can proceed? With-Skill Agent Output (Isolated)
The With-Skill Agent Output (Plugin)
Title: Labels I would apply:
The code modifies Apple-platform UISwitch extensions with iOS 26 / MacCatalyst 26 version guards, so both Apple platform labels apply. 📊 agentic-labeler / pr-does-not-get-triage-workflow-labelsJudge Report: PR does not get triage workflow labelsBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 4.3/5
With-Skill Judge (Plugin)Overall Score: 4/5
Baseline Agent Output
To proceed, I'd need either:
Could you provide a GitHub token or share what the PR is about? With-Skill Agent Output (Isolated)
Title: Changed file: Labels I would apply:
The PR fixes recycled CollectionView item views accumulating stale window-inset padding on Android, causing an increasing bottom gap while scrolling. With-Skill Agent Output (Plugin)
Title: Changed file: Labels I would apply:
The PR modifies Android-specific inset/safe-area logic, but the subject-matter focus is CollectionView's bottom gap during scrolling — so the control label wins over 📊 agentic-labeler / shell-area-shell-specific-source-filesJudge Report: Shell area - Shell-specific source filesBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 4.3/5
With-Skill Judge (Plugin)Overall Score: 4.3/5
Baseline Agent Output
To proceed, I'd need either:
Could you provide access to the GitHub API or share the PR details? With-Skill Agent Output (Isolated)
Title: "Bind badge properties when ShellContent is converted into an implicit ShellSection so badges set directly on ShellContent update the generated section." Changed files:
Labels I would apply:
No With-Skill Agent Output (Plugin)
Title: "Bind badge properties when ShellContent is converted into an implicit ShellSection so badges set directly on ShellContent update the generated section." Changed files:
Labels I would apply:
No This PR is already merged, so I cannot apply labels via the API due to token restrictions. But the correct label is 📊 agentic-labeler / skill-file-pr-gets-area-infrastructure-not-area-tooling-Judge Report: Skill-file PR gets area-infrastructure (not area-tooling)Baseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 4/5
With-Skill Judge (Plugin)Overall Score: 4/5
Baseline Agent Output
To proceed, I'd need either:
Could you provide a GitHub token or describe what PR #34962 is about so I can recommend labels? With-Skill Agent Output (Isolated)
Title: "Add Trim/NativeAOT safety rules to code review skill" Changed files: Labels I would apply:
No With-Skill Agent Output (Plugin)
Title: "Add Trim/NativeAOT safety rules to code review skill" Files changed: Labels I would apply:
No I'm unable to actually apply the labels due to a token authentication issue (the enterprise policy is rejecting the available token). Would you like me to try another approach to apply them, or is the label recommendation sufficient? 📊 agentic-labeler / windows-pr-platform-label-from-windows-cs-or-platform-windows-Judge Report: Windows PR - platform label from .windows.cs or Platform/Windows/Baseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 5/5
With-Skill Judge (Plugin)Overall Score: 4.7/5
Baseline Agent Output
To help you, I'd need either:
Could you provide the PR details or set up authentication ( With-Skill Agent Output (Isolated)
Changed file: Subject: Fixes Labels I would apply:
No other With-Skill Agent Output (Plugin)
Changed file: Subject matter: Fix for Labels I would apply:
No other 📊 agentic-labeler / workflow-only-pr-gets-area-infrastructureJudge Report: Workflow-only PR gets area-infrastructureBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 4.3/5
With-Skill Judge (Plugin)Overall Score: 4.3/5
Baseline Agent Output
To proceed, I'd need either:
Could you provide access credentials or share the PR context? With-Skill Agent Output (Isolated)
Title: Fix /review trigger leading whitespace handling Content: Modifies a GitHub Actions workflow file to add a pre-filter job that uses a bash regex to handle leading whitespace before Changed files: A Labels I would apply:
No With-Skill Agent Output (Plugin)
PR Summary: Fixes the Labels I would apply:
No However, I'm unable to apply the labels right now because the available GitHub token is rejected by the dotnet enterprise's access policy. To apply them, you'd run:
📊 agentic-labeler / xaml-source-generator-pr-gets-area-xamlJudge Report: XAML source generator PR gets area-xamlBaseline JudgeOverall Score: 1/5
With-Skill Judge (Isolated)Overall Score: 1.7/5
With-Skill Judge (Plugin)Overall Score: 2.7/5
Baseline Agent Output
To help you, I'd need either:
Could you provide access to the GitHub API or share the PR content? With-Skill Agent Output (Isolated)
PR Title: Replaces Content: This PR modifies/adds files under Labels I would apply:
No With-Skill Agent Output (Plugin)
PR Title: Replaces Changed files: All in Labels I would apply:
No This is a textbook |
This comment has been minimized.
This comment has been minimized.
kubaflo
left a comment
There was a problem hiding this comment.
Could you check the ai's suggestions?
Superseded by a newer MauiBot review run.
kubaflo
left a comment
There was a problem hiding this comment.
AI Review Summary
@NanthiniMahalingam — new AI review results are available based on this last commit:
01c3fbb.
Updated the fix and test case.
Review Sessions — click to expand
Gate — Test Before & After Fix
Gate Result: ❌ FAILED
Platform: WINDOWS · Base: main · Merge base: b0ea772f
🩺 Fix does not compile — applying the PR's fix produces a build error before tests can run. The earlier-than-test failure is the root cause; the per-test ❌ FAIL marks are downstream effects, not real test failures.
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🖥️ Issue29420 Issue29420 |
❌ PASS — 574s | 🛠️ BUILD ERROR |
🔴 Without fix — 🖥️ Issue29420: PASS ❌ · 574s
Determining projects to restore...
Restored D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj (in 41.21 sec).
Restored D:\a\1\s\src\Controls\Maps\src\Controls.Maps.csproj (in 41.05 sec).
Restored D:\a\1\s\src\Controls\Foldable\src\Controls.Foldable.csproj (in 291 ms).
Restored D:\a\1\s\src\BlazorWebView\src\Maui\Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 3.96 sec).
Restored D:\a\1\s\src\Graphics\src\Graphics.Win2D\Graphics.Win2D.csproj (in 17 ms).
Restored D:\a\1\s\src\Essentials\src\Essentials.csproj (in 17 ms).
Restored D:\a\1\s\src\Core\src\Core.csproj (in 56 ms).
Restored D:\a\1\s\src\Core\maps\src\Maps.csproj (in 18 ms).
Restored D:\a\1\s\src\Graphics\src\Graphics\Graphics.csproj (in 4.01 sec).
Restored D:\a\1\s\src\Controls\src\Xaml\Controls.Xaml.csproj (in 28 ms).
Restored D:\a\1\s\src\Controls\tests\TestCases.HostApp\Controls.TestCases.HostApp.csproj (in 727 ms).
3 of 14 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Essentials.dll
Graphics.Win2D -> D:\a\1\s\artifacts\bin\Graphics.Win2D\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.Win2D.WinUI.Desktop.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Core -> D:\a\1\s\artifacts\bin\Core\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Maps -> D:\a\1\s\artifacts\bin\Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Maps.dll
Controls.BindingSourceGen -> D:\a\1\s\artifacts\bin\Controls.BindingSourceGen\Debug\netstandard2.0\Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Controls.Core -> D:\a\1\s\artifacts\bin\Controls.Core\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Microsoft.AspNetCore.Components.WebView.Maui -> D:\a\1\s\artifacts\bin\Microsoft.AspNetCore.Components.WebView.Maui\Debug\net10.0-windows10.0.19041.0\Microsoft.AspNetCore.Components.WebView.Maui.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Controls.Foldable -> D:\a\1\s\artifacts\bin\Controls.Foldable\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Foldable.dll
Controls.Maps -> D:\a\1\s\artifacts\bin\Controls.Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Maps.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Controls.Xaml -> D:\a\1\s\artifacts\bin\Controls.Xaml\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Xaml.dll
Controls.TestCases.HostApp -> D:\a\1\s\artifacts\bin\Controls.TestCases.HostApp\Debug\net10.0-windows10.0.19041.0\win-x64\Controls.TestCases.HostApp.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:06:07.04
Determining projects to restore...
Restored D:\a\1\s\src\Controls\tests\CustomAttributes\Controls.CustomAttributes.csproj (in 843 ms).
Restored D:\a\1\s\src\TestUtils\src\VisualTestUtils\VisualTestUtils.csproj (in 4 ms).
Restored D:\a\1\s\src\TestUtils\src\VisualTestUtils.MagickNet\VisualTestUtils.MagickNet.csproj (in 4.77 sec).
Restored D:\a\1\s\src\Controls\tests\TestCases.WinUI.Tests\Controls.TestCases.WinUI.Tests.csproj (in 8.33 sec).
Restored D:\a\1\s\src\TestUtils\src\UITest.Core\UITest.Core.csproj (in 2 ms).
Restored D:\a\1\s\src\TestUtils\src\UITest.Appium\UITest.Appium.csproj (in 2 ms).
Restored D:\a\1\s\src\TestUtils\src\UITest.NUnit\UITest.NUnit.csproj (in 2.3 sec).
Restored D:\a\1\s\src\TestUtils\src\UITest.Analyzers\UITest.Analyzers.csproj (in 4.94 sec).
7 of 15 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0\Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0\Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Controls.CustomAttributes -> D:\a\1\s\artifacts\bin\Controls.CustomAttributes\Debug\net10.0\Controls.CustomAttributes.dll
Core -> D:\a\1\s\artifacts\bin\Core\Debug\net10.0\Microsoft.Maui.dll
Controls.Core.Design -> D:\a\1\s\artifacts\bin\Controls.Core.Design\Debug\net472\Microsoft.Maui.Controls.DesignTools.dll
Controls.BindingSourceGen -> D:\a\1\s\artifacts\bin\Controls.BindingSourceGen\Debug\netstandard2.0\Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Controls.Core -> D:\a\1\s\artifacts\bin\Controls.Core\Debug\net10.0\Microsoft.Maui.Controls.dll
UITest.Core -> D:\a\1\s\artifacts\bin\UITest.Core\Debug\net10.0\UITest.Core.dll
UITest.Appium -> D:\a\1\s\artifacts\bin\UITest.Appium\Debug\net10.0\UITest.Appium.dll
UITest.NUnit -> D:\a\1\s\artifacts\bin\UITest.NUnit\Debug\net10.0\UITest.NUnit.dll
VisualTestUtils -> D:\a\1\s\artifacts\bin\VisualTestUtils\Debug\netstandard2.0\VisualTestUtils.dll
VisualTestUtils.MagickNet -> D:\a\1\s\artifacts\bin\VisualTestUtils.MagickNet\Debug\netstandard2.0\VisualTestUtils.MagickNet.dll
UITest.Analyzers -> D:\a\1\s\artifacts\bin\UITest.Analyzers\Debug\netstandard2.0\UITest.Analyzers.dll
Controls.TestCases.WinUI.Tests -> D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
Test run for D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
NUnit3TestExecutor discovered 2 of 2 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 5/30/2026 5:18:14 PM FixtureSetup for Issue29420(Windows)
>>>>> 5/30/2026 5:18:22 PM VerifyCarouselViewKeepLastInViewOnItemInsert Start
>>>>> 5/30/2026 5:18:25 PM VerifyCarouselViewKeepLastInViewOnItemInsert Stop
Passed VerifyCarouselViewKeepLastInViewOnItemInsert [2 s]
>>>>> 5/30/2026 5:18:25 PM VerifyCarouselViewKeepLastInViewOnItemAdd Start
>>>>> 5/30/2026 5:18:27 PM VerifyCarouselViewKeepLastInViewOnItemAdd Stop
Passed VerifyCarouselViewKeepLastInViewOnItemAdd [1 s]
NUnit Adapter 4.5.0.0: Test execution complete
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.11] Discovering: Controls.TestCases.WinUI.Tests
[xUnit.net 00:00:00.33] Discovered: Controls.TestCases.WinUI.Tests
Results File: D:\a\1\s\CustomAgentLogsTmp\UITests\TestResults\Issue29420.trx
Test Run Successful.
Total tests: 2
Passed: 2
Total time: 33.3179 Seconds
>>> TRX_RESULT_FILE: D:\a\1\s\CustomAgentLogsTmp\UITests\TestResults\Issue29420.trx
🟢 With fix — 🖥️ Issue29420: 🛠️ BUILD ERROR · 169s
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Graphics.Win2D -> D:\a\1\s\artifacts\bin\Graphics.Win2D\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.Win2D.WinUI.Desktop.dll
Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
Core -> D:\a\1\s\artifacts\bin\Core\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.dll
Controls.BindingSourceGen -> D:\a\1\s\artifacts\bin\Controls.BindingSourceGen\Debug\netstandard2.0\Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14241503
D:\a\1\s\src\Controls\src\Core\Handlers\Items\CarouselViewHandler.Windows.cs(162,27): error RS0016: Symbol 'override Microsoft.Maui.Controls.Handlers.Items.CarouselViewHandler.UpdateEmptyViewVisibility() -> void' is not part of the declared public API (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
Maps -> D:\a\1\s\artifacts\bin\Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Maps.dll
Build FAILED.
D:\a\1\s\src\Controls\src\Core\Handlers\Items\CarouselViewHandler.Windows.cs(162,27): error RS0016: Symbol 'override Microsoft.Maui.Controls.Handlers.Items.CarouselViewHandler.UpdateEmptyViewVisibility() -> void' is not part of the declared public API (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
0 Warning(s)
1 Error(s)
Time Elapsed 00:02:38.87
⚠️ Failure Details
- ❌ Issue29420 PASSED without fix (should fail) — tests don't catch the bug
- 🛠️ Issue29420 with fix: build failed (fix does not compile)
📁 Fix files reverted (3 files)
eng/pipelines/ci-copilot.ymlsrc/Controls/src/Core/Handlers/Items/CarouselViewHandler.Windows.cssrc/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs
UI Tests — CarouselView,CollectionView
Detected UI test categories: CarouselView,CollectionView
Pre-Flight — Context & Validation
Issue: #29420 - KeepLastInView Not Working as Expected in CarouselView
PR: #29550 - Windows CarouselView KeepLastItemInView fix
Platforms Affected: Windows
Files Changed: 2 implementation, 2 test in the CarouselView/ItemsView area; PR branch also contains Copilot CI/script changes outside the product fix.
Key Findings
- GitHub CLI was unauthenticated, so PR description/comments/reviews could not be fetched through
gh; context was gathered from the checked-outpr-review-29550branch, local diff, the existing gate output, and public PR/patch access where available. - Gate output already exists and was not regenerated. It reports the PR fix fails to compile with RS0016 for
protected override CarouselViewHandler.UpdateEmptyViewVisibility(), and the addedIssue29420tests passed without the PR fix, so they do not prove the regression. - The code-review pass found a concrete product regression risk: the PR's new
ItemContainerStylereplaces the style-provided CarouselView stretch setters. - Impacted UI test category:
CarouselView.
Code Review Summary
Verdict: NEEDS_CHANGES
Confidence: high
Errors: 1 | Warnings: 1 | Suggestions: 0
Key code review findings:
- ❌
src/Controls/src/Core/Handlers/Items/CarouselViewHandler.Windows.cs:187and:198assign a newItemContainerStyle, replacing existing CarouselView style setters required for stretch layout. ⚠️ src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue29420.cs:20and:30use fixedTask.Delay(200)before screenshot verification; UI test guidance prefersVerifyScreenshot(..., retryTimeout: TimeSpan.FromSeconds(2)).
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #29550 | Updates CarouselView collection position handling, item sizing/spacing, empty-view template handling, and generic ItemsView item count null-safety. | ❌ FAILED (Gate build error) | CarouselViewHandler.Windows.cs, ItemsViewHandler.Windows.cs, UI test files |
Build fails with RS0016 because the protected override is missing from declared public API; code review also found ItemContainerStyle regression risk. |
Code Review — Deep Analysis
Code Review — PR #29550
Independent Assessment
What this changes: Windows CarouselView item updating/position behavior, item spacing sizing/padding, and adds Windows UI screenshot coverage.
Inferred motivation: Fix KeepLastItemInView and ScrollTo/current item drift with CarouselView on Windows.
Reconciliation with PR Narrative
Author claims: Fixes Windows CarouselView KeepLastItemInView and related ScrollTo/position issues.
Agreement/disagreement: The intent matches the code, but one implementation detail regresses existing item container styling.
Findings
❌ Error — New ItemContainerStyle drops required CarouselView stretch setters
src/Controls/src/Core/Handlers/Items/CarouselViewHandler.Windows.cs:187 and line 198 assign a new ItemContainerStyle. That overrides the ItemContainerStyle already provided by HorizontalCarouselListStyle / VerticalCarouselListStyle in ItemsViewStyles.xaml, which includes required stretch alignment setters:
- horizontal:
HorizontalAlignment=Stretch,HorizontalContentAlignment=Stretch - vertical:
VerticalAlignment=Stretch,VerticalContentAlignment=Stretch
The replacement style only sets Padding, so CarouselView items can stop stretching/filling correctly even when ItemSpacing is 0. Preserve the existing setters, base the style on the existing container style, or update the resource style rather than replacing it.
⚠️ Warning — UI test uses fixed delay before screenshot verification
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue29420.cs:20 and line 30 use await Task.Delay(200) before VerifyScreenshot. The UI test guidance explicitly discourages arbitrary delays before screenshot verification because they are flaky on slower CI. Prefer VerifyScreenshot(..., retryTimeout: TimeSpan.FromSeconds(2)) or a deterministic wait.
Devil's Advocate
The spacing math itself is plausible: subtracting one item spacing and applying half-padding can produce centered gaps. However, the style override concern is concrete because WinUI local ItemContainerStyle replaces the style-provided container style. CI was still pending/in progress, so it cannot be used to clear the regression risk.
Verdict: NEEDS_CHANGES
Confidence: high
Summary: The PR addresses the intended Windows CarouselView behavior, but the new container style drops existing alignment setters and can regress item layout. The fixed screenshot delay should also be cleaned up for test reliability.
Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix | Remove PR's public-API-breaking empty-view override and style/spacing changes; keep CarouselView-specific collection-position update plus generic null-safety. | ✅ PASS | 2 implementation + UI test files | Fixes build failure and avoids ItemContainerStyle regression; still changes CarouselView collection handling. |
| 2 | try-fix | Use only the existing generic Windows ItemsView vector-change scroll path, changing item-count selection for non-CollectionView handlers and adding null-safe ItemCount. |
✅ PASS | 1 implementation + UI test files | Smallest passing implementation; no CarouselView-specific collection rewrite, no public API change, no style override. |
| PR | PR #29550 | CarouselView-specific collection-position changes, item spacing/style changes, empty-view override, and generic item-count null-safety. | ❌ FAILED (Gate build error) | 2 implementation + UI test files | Build fails with RS0016; code review found new ItemContainerStyle drops required stretch setters. |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| code-review + maui-expert-reviewer guidance | 1 | Yes | Identified that the PR combines unrelated concerns. Generated a compile-safe CarouselView-specific candidate and a smaller generic ItemsView-path candidate. |
| gpt-5.5 local test loop | 1 | Yes | Candidate 2 demonstrated the scenario passes without CarouselView-specific collection rewrite, making it lower risk than candidate 1. |
Exhausted: Yes
Selected Fix: Candidate #2 — It passes the targeted Windows UI tests, avoids the PR's public API analyzer failure, avoids replacing CarouselView item-container styles, and changes the least product code.
Report — Final Recommendation
Comparative Report - PR #29550
Candidates compared
| Rank | Candidate | Regression result | Assessment |
|---|---|---|---|
| 1 | try-fix-2 |
PASS | Best candidate. It uses the existing generic Windows ItemsViewHandler.OnItemsVectorChanged path, changes item-count selection only where needed for non-CollectionView handlers, and adds null-safe ItemCount. It passed the targeted Windows UI regression tests and has the smallest product-code surface. |
| 2 | try-fix-1 |
PASS | Also viable. It removes the PR's public API-breaking empty-view override and style/spacing changes while retaining a CarouselView-specific collection-position update. It passed the targeted Windows UI regression tests, but it changes more CarouselView-specific behavior than try-fix-2. |
| 3 | pr-plus-reviewer |
FAILED / not viable | Applies the expert reviewer's test robustness feedback by replacing fixed screenshot delays with retry timeouts. However, it keeps the PR's known compile failure and the pre-flight item-container style regression risk, so it cannot outrank passing candidates. |
| 4 | pr |
FAILED | Raw PR fix failed the gate with RS0016 for CarouselViewHandler.UpdateEmptyViewVisibility() and pre-flight review found that its new ItemContainerStyle drops existing CarouselView stretch setters. |
Key comparison points
try-fix-2 is the lowest-risk passing implementation because it demonstrates the issue can be addressed through the existing generic Windows vector-change scroll path. It avoids the raw PR's public API analyzer failure, avoids replacing CarouselView item-container styles, and avoids the broader CarouselView-specific collection synchronization rewrite used by try-fix-1.
try-fix-1 is acceptable but less preferred: it passes the same targeted tests and removes the PR's highest-risk style/public API changes, but it retains a new _isInternalPositionUpdate path and explicit CarouselView collection-position handling. That extra behavior is not necessary based on try-fix-2 passing.
The PR-family candidates (pr and pr-plus-reviewer) are ranked below both passing try-fix candidates because candidates that failed regression/build validation must rank lower than candidates that passed. The expert reviewer feedback improves test quality only; it does not repair the known PR build blocker.
Winner
try-fix-2 is the single winning candidate. It is the smallest candidate that passed the targeted Windows regression tests while avoiding the raw PR's compile failure and item-container styling regression risk.
Future Action — alternative fix proposed (try-fix-2)
Automated review — alternative fix proposed
The expert-reviewer evaluation compared the PR fix against automatically generated candidates and selected try-fix-2 as the strongest fix.
Why: try-fix-2 won because it passed the targeted Windows regression tests with the smallest product-code change. It avoids the raw PR and pr-plus-reviewer compile failure and avoids the PR item-container style regression risk.
Please consider applying the candidate diff below (or use it as guidance). Once you push an update, this workflow will re-trigger and re-evaluate.
Candidate diff (try-fix-2)
diff --git a/src/Controls/src/Core/Handlers/Items/CarouselViewHandler.Windows.cs b/src/Controls/src/Core/Handlers/Items/CarouselViewHandler.Windows.cs
index 624a1db702..a649656d75 100644
--- a/src/Controls/src/Core/Handlers/Items/CarouselViewHandler.Windows.cs
+++ b/src/Controls/src/Core/Handlers/Items/CarouselViewHandler.Windows.cs
@@ -334,9 +334,7 @@ namespace Microsoft.Maui.Controls.Handlers.Items
void SetCarouselViewPosition(int position)
{
if (ItemCount == 0)
- {
return;
- }
if (!IsValidPosition(position))
return;
@@ -578,7 +576,6 @@ namespace Microsoft.Maui.Controls.Handlers.Items
if (removingCurrentElementButNotFirst)
{
carouselPosition = ItemsView.Position - 1;
-
}
else if (removingFirstElement && !removingCurrentElement)
{
@@ -639,5 +636,6 @@ namespace Microsoft.Maui.Controls.Handlers.Items
item.ItemWidth = itemWidth;
}
}
+
}
}
diff --git a/src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs b/src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs
index afe9aa668d..aaa05b7253 100644
--- a/src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs
+++ b/src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs
@@ -148,7 +148,11 @@ namespace Microsoft.Maui.Controls.Handlers.Items
return;
}
- var itemsCount = items.Count;
+ // When looping is enabled in CarouselView, Items. Count returns
+ // the FakeCount instead of the actual item count.
+ // Use items.Count for CollectionView to account for this
+ // behavior: otherwise, use ItemCount for other types.
+ var itemsCount = VirtualView is CollectionView ? items.Count : ItemCount;
if (itemsCount == 0)
{
@@ -703,7 +707,7 @@ namespace Microsoft.Maui.Controls.Handlers.Items
return null;
}
- protected virtual int ItemCount => CollectionViewSource.View.Count;
+ protected virtual int ItemCount => CollectionViewSource is not null ? CollectionViewSource.View.Count : 0;
protected virtual object GetItem(int index)
{
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue29420.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue29420.cs
new file mode 100644
index 0000000000..4e2ddb3cd7
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue29420.cs
@@ -0,0 +1,76 @@
+using System.Collections.ObjectModel;
+
+namespace Maui.Controls.Sample.Issues;
+[Issue(IssueTracker.Github, 29420, "KeepLastInView Not Working as Expected in CarouselView", PlatformAffected.UWP)]
+public class Issue29420 : ContentPage
+{
+ public Issue29420()
+ {
+ var count = 0;
+ var verticalStackLayout = new VerticalStackLayout();
+ var carouselItems = new ObservableCollection<string>
+ {
+ "Item 0", "Item 1","Item 2", "Item 3", "Item 4", "Item 5",
+
+ };
+
+ CarouselView carouselView = new CarouselView
+ {
+ ItemsSource = carouselItems,
+ AutomationId = "CarouselView",
+ Loop = false,
+ ItemsUpdatingScrollMode = ItemsUpdatingScrollMode.KeepLastItemInView,
+
+ ItemTemplate = new DataTemplate(() =>
+ {
+ var grid = new Grid
+ {
+ Padding = 10
+ };
+
+ var label = new Label
+ {
+ VerticalOptions = LayoutOptions.Center,
+ HorizontalOptions = LayoutOptions.Center,
+ FontSize = 18,
+ Background = Colors.Pink,
+ };
+ label.SetBinding(Label.TextProperty, ".");
+ label.SetBinding(Label.AutomationIdProperty, ".");
+
+ grid.Children.Add(label);
+ return grid;
+ }),
+ };
+
+ var insertButton = new Button
+ {
+ Text = "Insert item at 0th index",
+ AutomationId = "InsertButton",
+ Margin = new Thickness(20),
+ };
+
+ var addButton = new Button
+ {
+ Text = "Add item at end",
+ AutomationId = "AddButton",
+ Margin = new Thickness(20),
+ };
+
+ insertButton.Clicked += (sender, e) =>
+ {
+ carouselItems.Insert(0, "NewItem" + count.ToString());
+ count++;
+ };
+
+ addButton.Clicked += (sender, e) =>
+ {
+ carouselItems.Add("NewItem");
+ };
+
+ verticalStackLayout.Children.Add(insertButton);
+ verticalStackLayout.Children.Add(addButton);
+ verticalStackLayout.Children.Add(carouselView);
+ Content = verticalStackLayout;
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue29420.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue29420.cs
new file mode 100644
index 0000000000..2d50b25d19
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue29420.cs
@@ -0,0 +1,34 @@
+#if TEST_FAILS_ON_ANDROID && TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST // CarouselView Fails to Keep Last Item in View on iOS, android and macOS https://github.com/dotnet/maui/issues/18029, https://github.com/dotnet/maui/issues/29415
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues;
+public class Issue29420 : _IssuesUITest
+{
+ public override string Issue => "KeepLastInView Not Working as Expected in CarouselView";
+
+ public Issue29420(TestDevice device) : base(device)
+ { }
+
+ [Test, Order(1)]
+ [Category(UITestCategories.CarouselView)]
+ public async Task VerifyCarouselViewKeepLastInViewOnItemInsert()
+ {
+ App.WaitForElement("CarouselView");
+ App.Tap("InsertButton");
+ await Task.Delay(200); // Wait for the scrollbar to disappear.
+ VerifyScreenshot("CarouselViewKeepLastInViewOnItemInsert");
+ }
+
+ [Test, Order(2)]
+ [Category(UITestCategories.CarouselView)]
+ public async Task VerifyCarouselViewKeepLastInViewOnItemAdd()
+ {
+ App.WaitForElement("CarouselView");
+ App.Tap("AddButton");
+ await Task.Delay(200); // Wait for the scrollbar to disappear.
+ VerifyScreenshot("CarouselViewKeepLastInViewOnItemAdd");
+ }
+}
+#endif
\ No newline at end of file
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!
Root Cause
Description of Change
Validated the behaviour in the following platforms
Issues Fixed
Fixes #29420
Fixes #29448
Output
Windows
Issue29420_Before.mp4
Issue29420_After.mp4