Skip to content

[Android] - Fix Inconsistent Footer Scrolling Behaviour in CollectionView with EmptyView#28107

Merged
kubaflo merged 5 commits intodotnet:inflight/currentfrom
prakashKannanSf3972:fix-28101
Mar 17, 2026
Merged

[Android] - Fix Inconsistent Footer Scrolling Behaviour in CollectionView with EmptyView#28107
kubaflo merged 5 commits intodotnet:inflight/currentfrom
prakashKannanSf3972:fix-28101

Conversation

@prakashKannanSf3972
Copy link
Copy Markdown
Contributor

@prakashKannanSf3972 prakashKannanSf3972 commented Feb 28, 2025

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!

RootCause

When using a DataTemplate for headers or footers in a CollectionView, the generated views lack proper handler initialization by default. This results in incorrect size calculations, causing the header or footer to have a measured size of zero (0), which affects layout rendering and scrolling behavior.

Description of Change

This change ensures proper handler initialization for views created from a DataTemplate, allowing accurate size measurement and proper layout behavior.

Issues Fixed

Fixes #28101

Tested the behaviour in the following platforms

  • Android (primary - bug in Android only)
  • Windows
  • iOS
  • Mac

Output

Before After
BeforeFix.mov
AfterFix.mov

@dotnet-policy-service dotnet-policy-service bot added community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration labels Feb 28, 2025
@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz jsuarezruiz added platform/android area-controls-collectionview CollectionView, CarouselView, IndicatorView labels Mar 3, 2025
@prakashKannanSf3972 prakashKannanSf3972 marked this pull request as ready for review March 4, 2025 11:19
Copilot AI review requested due to automatic review settings March 4, 2025 11:19
@prakashKannanSf3972 prakashKannanSf3972 requested a review from a team as a code owner March 4, 2025 11:19
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

PR Overview

This PR fixes the inconsistent footer scrolling behavior in CollectionView when an EmptyView is active on Android by ensuring proper handler initialization for views created by DataTemplates.

  • Added test cases to verify the corrected scrolling behavior
  • Updated the host app UI to include DataTemplates for header and footer
  • Adjusted the Android adapter to initialize the handler when missing

Reviewed Changes

File Description
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/28101.cs Added a UI test to validate footer behavior
src/Controls/tests/TestCases.HostApp/Issues/Issue28101.cs Updated the CollectionView UI with header and footer templates
src/Controls/src/Core/Handlers/Items/Android/Adapters/EmptyViewAdapter.cs Fixed handler initialization for views from DataTemplates

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

Comments suppressed due to low confidence (2)

src/Controls/src/Core/Handlers/Items/Android/Adapters/EmptyViewAdapter.cs:320

  • Ensure that 'content' is a valid View before casting with 'as View' when calling TemplateHelpers.GetHandler to avoid potential null reference issues.
if (content?.Handler is null)

src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/28101.cs:18

  • [nitpick] Consider enhancing the test by adding assertions to verify that the footer's height is correctly measured and not zero, rather than only checking for the element's presence.
App.WaitForElement("This Is A Footer");

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/rebase

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/rebase

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/rebase

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run MAUI-UITests-public

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/rebase

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/rebase

PureWeen and others added 2 commits March 11, 2026 18:28
…hot fallback (dotnet#34340)

<!-- 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!

## Description

This PR brings together three improvements to the Copilot CI
infrastructure:

1. **Auto-trigger uitests and device-tests on `darc-*` branches** —
Major rework of `ci-copilot.yml` to support UI tests and device tests
triggered on darc branches.

2. **Make emulator startup and provisioning more robust** — Improvements
to `Start-Emulator.ps1` and `provision.yml` for more reliable Android
emulator handling.

3. **Support fallback environment for snapshots** — Changes to
`UITest.cs` and `VisualRegressionTester.cs` to support snapshot
environment fallback.

## Changes

- `eng/pipelines/ci-copilot.yml` — Reworked CI pipeline for Android
device test support
- `.github/scripts/shared/Start-Emulator.ps1` — More robust emulator
startup
- `eng/pipelines/common/provision.yml` — Provisioning improvements
- `src/Controls/tests/TestCases.Shared.Tests/UITest.cs` — Snapshot
fallback support
- `src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs` —
Snapshot fallback support

---------

Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…#34428) (dotnet#34449)

<!-- 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!

## Description

Cherry-pick of
[`5d6e5a20`](dotnet@5d6e5a2)
from `net11.0`, adapted for `main`.

Fixes dotnet#34428

### Problem

Release 10.0.50 introduced a performance optimization (`_isSubscribed`
flag) in `TypedBinding` that prevented re-subscribing to intermediate
INPC objects when they changed. This caused compiled bindings with
nested property paths (e.g. `{Binding ViewModel.Text}`) to stop updating
when the intermediate object was replaced.

### Fix

Remove the `_isSubscribed` guard and always call `Subscribe()` on every
`Apply`. The `Subscribe()` implementation is already idempotent — it
diffs old vs new subscription targets — so calling it repeatedly is safe
with minimal overhead.

### Tests

Two regression tests added to `TypedBindingUnitTests.cs`:
-
`TypedBinding_NestedProperty_ResubscribesAfterNullIntermediateBecomesNonNull`
- `TypedBinding_NestedProperty_ResubscribesAfterIntermediateReplaced`

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented Mar 15, 2026

🤖 AI Summary

📊 Expand Full Review8c63d32 · Fixed-Scrollable-FooterTemplate
🔍 Pre-Flight — Context & Validation

Issue: #28101 - CollectionView Footer Becomes Scrollable When EmptyView is Active on Android
PR: #28107 - [Android] Fix Inconsistent Footer Scrolling Behaviour in CollectionView with EmptyView
Author: prakashKannanSf3972 (Syncfusion partner)
Platforms Affected: Android only
Files Changed: 1 implementation, 2 test

Key Findings

  • When CollectionView displays an EmptyView, the footer/header templates are re-measured via UpdateHeaderFooterHeight() in EmptyViewAdapter.cs
  • Views created from DataTemplate.CreateContent() do not automatically have a handler initialized
  • Without a handler, content.Measure() returns (0, 0) — causing zero-height footer/header
  • On Android, a zero-height footer is placed inside the RecyclerView scrollable area (instead of fixed), making it scroll with content
  • On other platforms this code path differs, which is why the bug is Android-specific
  • Fix: Before measuring, check content.Handler is null and call TemplateHelpers.GetHandler() to initialize it
  • Test is a simple visibility check: App.WaitForElement("This Is A Footer") — verifies footer is visible at all

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #28107 Initialize handler via TemplateHelpers.GetHandler() before Measure() in UpdateHeaderFooterHeight() ⏳ PENDING (Gate) EmptyViewAdapter.cs Android-only fix in Items/ handler

Files Changed

  • Fix: src/Controls/src/Core/Handlers/Items/Android/Adapters/EmptyViewAdapter.cs (+5 lines)
  • Test (HostApp): src/Controls/tests/TestCases.HostApp/Issues/Issue28101.cs (new, +54 lines)
  • Test (Shared): src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/28101.cs (new, +20 lines)

Prior Agent Reviews

None found.


🚦 Gate — Test Verification

Gate Result: ✅ PASSED

Platform: Android
Mode: Full Verification

  • Tests FAIL without fix: ✅
  • Tests PASS with fix: ✅

Details:

  • Fix file: src/Controls/src/Core/Handlers/Items/Android/Adapters/EmptyViewAdapter.cs
  • Test filter: Issue28101
  • Without fix: FooterTemplateShouldNotScrollWhenEmptyViewIsDisplayed fails (footer not visible — measured as 0 height)
  • With fix: Test passes (footer rendered with proper height)

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #28107 Guard content.Handler is nullTemplateHelpers.GetHandler()content.Measure() ✅ PASSED (Gate) EmptyViewAdapter.cs (+5 lines) Minimal, synchronous, targeted
1 try-fix (sonnet) TemplateHelpers.GetHandler() → native platformView.Measure(MeasureSpec.Unspecified) → manual pixel→DP conversion ✅ PASS EmptyViewAdapter.cs (+9/-1 lines) Different measurement pipeline; more complex than PR fix
2 try-fix (opus) RemeasureBoundHeaderFooter() in OnBindViewHolder; posts NotifyDataSetChanged() if height was 0 ✅ PASS EmptyViewAdapter.cs (+47 lines) Reactive/post-hoc; NotifyDataSetChanged can be expensive
3 try-fix (sonnet) IOnLayoutChangeListener on header/footer ItemViews in OnCreateViewHolder; posts NotifyItemChanged() ✅ PASS EmptyViewAdapter.cs (+53/-10 lines) Async/reactive; requires Java object lifecycle management
4 try-fix (opus) Collapse 3-item RecyclerView to single LinearLayout item with layout_weight=1 for empty view ❌ FAIL EmptyViewAdapter.cs (+226/-107 lines) MAUI's ItemContentView incompatible when nested inside LinearLayout weight pass

Cross-Pollination

Model Round New Ideas? Details
claude-sonnet-4.6 1 Yes Event-driven via HandlerChanged event (→ became Attempt 3)
claude-opus-4.6 1 Yes Disable RecyclerView scrolling when EmptyViewAdapter active (symptom-fix, skipped)
claude-sonnet-4.6 2 Yes Single LinearLayout item (→ became Attempt 4, failed)
claude-opus-4.6 2 Yes Single LinearLayout item (same idea → Attempt 4)
claude-sonnet-4.6 3 Yes Dynamic LayoutManager.FindViewByPosition() queries in GetHeight()
claude-opus-4.6 3 Yes Custom LayoutManager subclass for empty state

Exhausted: Yes (max 3 cross-pollination rounds reached)

Selected Fix: PR's fix — Reason: Simplest, most minimal (+5 lines), directly addresses root cause (handler not initialized before measurement). All passing alternatives (Attempts 1-3) achieve the same result with significantly more code, added complexity, or side effects (e.g., NotifyDataSetChanged cost in Attempt 2, Java listener lifecycle in Attempt 3). The PR's synchronous guard-and-initialize approach is the cleanest solution.


📋 Report — Final Recommendation

✅ Final Recommendation: APPROVE

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #28101 — Android-only, CollectionView footer scrolls with EmptyView
Gate ✅ PASSED Android; tests FAIL without fix, PASS with fix
Try-Fix ✅ COMPLETE 4 attempts (3 passing, 1 failing); 3 cross-pollination rounds exhausted
Report ✅ COMPLETE

Summary

PR #28107 fixes an Android-specific bug where a CollectionView's footer (defined via FooterTemplate) becomes scrollable when an EmptyView is displayed. The fix is a minimal 5-line change to EmptyViewAdapter.cs. Gate verification confirmed the tests correctly reproduce the bug and validate the fix. Three independent alternative fixes were found via try-fix exploration — all confirmed the same root cause — but all require significantly more code than the PR's approach.

Root Cause

In EmptyViewAdapter.UpdateHeaderFooterHeight(), when the item is a DataTemplate, the method calls dataTemplate.CreateContent() to get a view and immediately calls content.Measure(). However, views created from DataTemplate.CreateContent() have no handler initialized by default. Without a handler, Measure() returns (0, 0), so _footerHeight is stored as 0. The GetHeight() method uses RecyclerViewHeight - _headerHeight - _footerHeight to size the empty view — with a 0-height footer, the empty view expands to fill the full RecyclerView height, pushing the footer into the scrollable area.

Fix Quality

The PR's fix is correct, minimal, and well-targeted:

  • Adds a guard if (content?.Handler is null) before calling TemplateHelpers.GetHandler(content as View, ItemsView.FindMauiContext()), which initializes the handler
  • After initialization, content.Measure() returns correct dimensions, so _footerHeight is properly stored
  • Only 5 lines added, no structural changes to the adapter
  • Fix is in the Items/Android/ path (not the deprecated Items2/), which is correct for Android

Minor observation: The null-conditional on content?.Handler is good defensiveness, but content itself could theoretically be null if DataTemplate.CreateContent() returns something that isn't an IView. If null, TemplateHelpers.GetHandler(null as View, ...) would be called, and then size = content.Measure(...) would throw NullReferenceException — but this is a pre-existing issue not introduced by this PR.

Test quality: The test (FooterTemplateShouldNotScrollWhenEmptyViewIsDisplayed) simply waits for the footer element to be visible. This is minimal but sufficient — before the fix the footer measures as 0-height and isn't accessible/visible; after the fix it's correctly sized and visible.

Fix Comparison

Fix Lines Changed Complexity Risk
PR's fix (selected) +5 Low Low
Attempt 1 (native measurement) +9/-1 Medium Low (manual DP conversion adds density-assumption risk)
Attempt 2 (OnBindViewHolder re-measure) +47 Medium Medium (NotifyDataSetChanged overhead)
Attempt 3 (LayoutChangeListener) +53/-10 High Medium (Java object lifecycle)
Attempt 4 (LinearLayout single item) +226/-107 Very High High (FAILED — incompatible with ItemContentView)

Result: Selected Fix: PR


📋 Expand PR Finalization Review

PR #28107 Finalization Review

PR: #28107[Android] - Fix Inconsistent Footer Scrolling Behaviour in CollectionView with EmptyView
Author: prakashKannanSf3972 (Syncfusion partner)
Issue Fixed: #28101
Changed Files: 3 (1 fix, 2 tests)


Phase 1: Title & Description Review

⚠️ Title: Needs Minor Update

Current: [Android] - Fix Inconsistent Footer Scrolling Behaviour in CollectionView with EmptyView

Issues:

  • The - separator after [Android] is non-standard (other MAUI PRs use [Android] Component: ...)
  • "Behaviour" is British spelling; the codebase uses American English "Behavior"
  • Verbose; can be more precise

Recommended:

[Android] CollectionView: Fix footer scrolling when EmptyView is displayed

⚠️ Description: Needs Additions

Quality Assessment:

Indicator Status Notes
Structure Clear sections: Root Cause, Description, Issues Fixed
Technical depth 🟡 Root cause is clear but lacks explanation of why handler init was missing
Accuracy Claims tested on Windows, iOS, Mac — but this is Android-only (the fix is in Items/Android/)
Completeness Missing required NOTE block; Before/After output table has empty cells

Required additions:

  1. Missing NOTE block — Must be prepended to top per contribution guidelines
  2. Inaccurate platform testing checklist — The fix is in Handlers/Items/Android/; Windows, iOS, and Mac checkboxes should be unchecked unless the bug was independently reproduced there
  3. Empty "Output" table — The before/after screenshot table has empty cells; should include screenshots or be removed

Recommended description:

<!-- 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!

### Root Cause

When `HeaderTemplate` or `FooterTemplate` in a `CollectionView` uses a `DataTemplate`, the content view
is created via `dataTemplate.CreateContent()` but its MAUI handler is never initialized. Without a
handler, `IView.Measure()` returns zero — causing the header/footer to have a calculated height of 0.
With an incorrect (zero) height, the RecyclerView treats the footer as having no size, allowing it to
scroll with the empty view content.

The `IView` code path (direct view, not a `DataTemplate`) already had the correct handler-initialization
guard — it was only missing in the `DataTemplate` branch of `UpdateHeaderFooterHeight`.

### Description of Change

In `EmptyViewAdapter.UpdateHeaderFooterHeight`, added a handler-initialization check before measuring
`DataTemplate`-created views — mirroring the pattern already present for direct `IView` items:

```csharp
if (content?.Handler is null)
{
    TemplateHelpers.GetHandler(content as View, ItemsView.FindMauiContext());
}

This ensures accurate size measurement so the footer is correctly positioned and does not scroll.

Issues Fixed

Fixes #28101

Platforms Tested

  • Android (primary — bug is Android-only)
  • iOS
  • Windows
  • Mac

---

## Phase 2: Code Review

### ✅ Looks Good

- **Pattern consistency:** The fix mirrors the existing `IView` handler-initialization guard (lines 308–311) exactly. Same null-check pattern, same `TemplateHelpers.GetHandler()` call, same `content as View` cast.
- **Minimal/surgical change:** Only 5 lines added; no unrelated changes.
- **`[Category(UITestCategories.CollectionView)]`** is correctly applied.
- **HostApp test** correctly uses `TestContentPage` base class with `Init()` pattern and sets up the exact repro scenario (empty CollectionView with both HeaderTemplate and FooterTemplate).

### 🟡 Suggestions

**1. Test file naming inconsistency**
- `src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/28101.cs` — Missing `Issue` prefix
- Convention in the surrounding files is `Issue28101.cs` (see: `Issue28051.cs`, `Issue28098.cs`, etc.)
- **Recommendation:** Rename to `Issue28101.cs`

**2. Test lacks `AutomationId` and uses text-based element lookup**
```csharp
// Current
App.WaitForElement("This Is A Footer");

The test locates the footer by its display text ("This Is A Footer"). This will break if the text changes and is not the conventional approach.

  • Recommendation: Add AutomationId = "FooterLabel" to the label in the HostApp and use App.WaitForElement("FooterLabel") in the test.

3. Test validates visibility, not the actual bug (scrolling behavior)
The original bug is that the footer becomes scrollable (not invisible). The current test only checks that the footer element is reachable by Appium — not that it's in the correct fixed position. A more faithful test would scroll the RecyclerView and verify the footer remains at the bottom.

  • Recommendation (optional): After WaitForElement, scroll up/down and re-verify the footer is still visible at its original position. This is a significant enhancement that may not be worth blocking the PR over, but is worth noting.

4. Missing newline at end of file
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/28101.cs has \ No newline at end of file in the diff.

  • Recommendation: Add a trailing newline.

🔴 Critical Issues

None. The core fix is correct and safe.


Summary

Category Status
Title ⚠️ Minor update recommended
NOTE block ❌ Missing — must be added
Description accuracy ❌ Platform testing checklist is inaccurate (claims iOS/Windows/Mac tested)
Core fix correctness ✅ Correct — mirrors existing pattern
Test naming ⚠️ Missing Issue prefix
Test robustness 🟡 Tests presence only, not scrolling behavior
Trailing newline ⚠️ Missing in test file

Overall: The fix is correct and well-targeted. Before merge:

  1. Add the NOTE block to the description
  2. Correct the platform testing checkboxes (Android only)
  3. Rename 28101.csIssue28101.cs in TestCases.Shared.Tests
  4. Add trailing newline to the test file
  5. Consider adding AutomationId to the footer label for a more robust test

@kubaflo kubaflo added s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Mar 15, 2026
PureWeen and others added 2 commits March 16, 2026 11:45
…xt skill (dotnet#34438)

<!-- 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!

## Summary

This PR adopts the
[`dotnet/arcade-skills`](https://github.com/dotnet/arcade-skills) plugin
system for CI investigation in dotnet/maui, replacing the need for
custom in-repo PowerShell scripts.

Two files are added:
1. **`.github/copilot/settings.json`** — repo-level plugin declaration
that auto-installs the `dotnet-dnceng` plugin for all users
2. **`.github/skills/azdo-build-investigator/SKILL.md`** — thin
MAUI-specific context supplement (~60 lines, no scripts)

---

## Background & Motivation

### The Problem

When investigating CI failures on dotnet/maui PRs, contributors and AI
agents need to:
- Query Azure DevOps builds across 3 pipelines (`maui-pr`,
`maui-pr-devicetests`, `maui-pr-uitests`)
- Dig into Helix test logs for device test failures
- Analyze MSBuild binlogs for obscure build failures
- Detect hidden test failures caused by XHarness exiting with code 0
even when tests fail

PR dotnet#34335 (`feature/azdo-ci-instructions`) addressed this with ~700
lines of custom PowerShell scripts. During review of that PR, we
discovered
[`dotnet/arcade-skills`](https://github.com/dotnet/arcade-skills) — a
.NET engineering-maintained plugin that provides native MCP tooling for
exactly this problem space, and already lists `dotnet/maui` as a
supported repository.

### Why arcade-skills Instead of Custom Scripts

The `dotnet-dnceng` plugin in arcade-skills provides:

| MCP Server | Tool | Replaces |
|------------|------|---------|
| `ado-dnceng-public` | Native ADO queries via `@azure-devops/mcp` |
`Get-BuildInfo.ps1`, `Get-BuildErrors.ps1`, `Get-PrBuildIds.ps1` |
| `hlx` | Helix test infrastructure via `lewing.helix.mcp` |
`Get-HelixLogs.ps1` |
| `mcp-binlog-tool` | MSBuild binlog analysis via `baronfel.binlog.mcp`
| `Get-BuildBinlogs.ps1` + manual `binlogtool` |

MCP tools are first-class AI primitives — the AI calls them directly
with structured parameters rather than running shell scripts and parsing
text output. This is more reliable and maintainable.

### Auto-Loading (No User Action Required)

The key mechanism that makes this work seamlessly:

**`.github/copilot/settings.json`** supports `enabledPlugins`
(introduced in Copilot CLI v0.0.422) — a "declarative plugin
auto-install" that runs at session startup when a user opens this
repository. Every user who opens dotnet/maui gets the `dotnet-dnceng`
plugin with all its MCP servers automatically. No `/plugin install`
command needed.

```json
{
  "extraKnownMarketplaces": [
    { "url": "https://github.com/dotnet/arcade-skills" }
  ],
  "enabledPlugins": ["dotnet-dnceng@dotnet-arcade-skills"]
}
```

---

## What the MAUI Context Skill Adds

The arcade-skills `ci-analysis` skill is excellent but contains outdated
MAUI-specific information (it lists `maui-public` as the pipeline name,
which is wrong). The thin `azdo-build-investigator/SKILL.md` provides
corrections and MAUI-specific domain knowledge:

### Correct Pipeline Names/IDs

| Pipeline | Definition ID | Purpose |
|----------|--------------|---------|
| `maui-pr` | **302** | Main build — check first |
| `maui-pr-devicetests` | **314** | Helix device tests |
| `maui-pr-uitests` | **313** | Appium UI tests |

### XHarness Exit-0 Blind Spot

XHarness (used in `maui-pr-devicetests`) **exits with code 0 even when
tests fail**. The ADO job shows ✅ "Succeeded" while actual test failures
hide inside Helix work items. The SKILL.md documents how to detect this
via the Helix `ResultSummaryByBuild` API.

This quirk was discovered while investigating PRs with the
`s/agent-gate-failed` label where CI appeared green but tests were
actually failing.

### Container Artifact Quirk for Binlogs

MAUI build artifacts are **Container type** (not `PipelineArtifact`), so
standard `az pipelines runs artifact download` does not work for
binlogs. The SKILL.md documents the correct download approach using the
ADO File Container API with Bearer auth.

---

## Relationship to PR dotnet#34335

PR dotnet#34335 (`feature/azdo-ci-instructions`) adds the same investigation
capability via 5 custom PowerShell scripts. This PR supersedes that
approach. The knowledge gained building those scripts (XHarness exit-0
discovery, Container artifact API approach, pipeline IDs) is preserved
in the SKILL.md here.

We recommend closing dotnet#34335 in favor of this approach, which:
- Has ~5% of the code to maintain
- Uses MCP tooling that will improve over time as arcade-skills evolves
- Auto-loads for all contributors without any setup

---

## Files Changed

```
.github/copilot/settings.json                    (new) — repo-level plugin auto-install
.github/skills/azdo-build-investigator/SKILL.md  (new) — MAUI-specific CI context
```

## Testing

- Verified `.github/copilot/settings.json` schema matches Copilot CLI
v0.0.422+ `enabledPlugins` format
- Verified `dotnet-dnceng@dotnet-arcade-skills` resolves against the
marketplace at
`https://github.com/dotnet/arcade-skills/.github/plugin/marketplace.json`
- SKILL.md pipeline IDs verified against live ADO builds: maui-pr=302,
maui-pr-devicetests=314, maui-pr-uitests=313

/cc @PureWeen

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 17, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 28107

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 28107"

@SyedAbdulAzeemSF4852
Copy link
Copy Markdown
Contributor

Addressed concerns raised in the AI summary.

@kubaflo kubaflo changed the base branch from main to inflight/current March 17, 2026 12:47
@kubaflo kubaflo merged commit a9a24ec into dotnet:inflight/current Mar 17, 2026
7 of 13 checks passed
PureWeen pushed a commit that referenced this pull request Mar 19, 2026
…View with EmptyView (#28107)

<!-- 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)](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!
### RootCause

When using a `DataTemplate` for headers or footers in a
`CollectionView`, the generated views lack proper handler initialization
by default. This results in incorrect size calculations, causing the
header or footer to have a measured size of zero (0), which affects
layout rendering and scrolling behavior.

### Description of Change

This change ensures proper handler initialization for views created from
a `DataTemplate`, allowing accurate size measurement and proper layout
behavior.

### Issues Fixed

Fixes #28101 

**Tested the behaviour in the following platforms**

- [x] Android (primary - bug in Android only)
- [ ]  Windows
- [ ]  iOS
- [ ] Mac

### Output 

|Before|After|
|--|--|
|<video
src="https://github.com/user-attachments/assets/314539cc-9307-4cf1-aa8e-566e3cb0ef1a">|
<video
src="https://github.com/user-attachments/assets/18004a13-e6b7-4331-ba3a-ca1f017ca6a8">|

---------
Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
PureWeen pushed a commit that referenced this pull request Mar 24, 2026
…View with EmptyView (#28107)

<!-- 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)](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!
### RootCause

When using a `DataTemplate` for headers or footers in a
`CollectionView`, the generated views lack proper handler initialization
by default. This results in incorrect size calculations, causing the
header or footer to have a measured size of zero (0), which affects
layout rendering and scrolling behavior.

### Description of Change

This change ensures proper handler initialization for views created from
a `DataTemplate`, allowing accurate size measurement and proper layout
behavior.

### Issues Fixed

Fixes #28101 

**Tested the behaviour in the following platforms**

- [x] Android (primary - bug in Android only)
- [ ]  Windows
- [ ]  iOS
- [ ] Mac

### Output 

|Before|After|
|--|--|
|<video
src="https://github.com/user-attachments/assets/314539cc-9307-4cf1-aa8e-566e3cb0ef1a">|
<video
src="https://github.com/user-attachments/assets/18004a13-e6b7-4331-ba3a-ca1f017ca6a8">|

---------
Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
KarthikRajaKalaimani pushed a commit to KarthikRajaKalaimani/maui that referenced this pull request Mar 30, 2026
…View with EmptyView (dotnet#28107)

<!-- 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)](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!
### RootCause

When using a `DataTemplate` for headers or footers in a
`CollectionView`, the generated views lack proper handler initialization
by default. This results in incorrect size calculations, causing the
header or footer to have a measured size of zero (0), which affects
layout rendering and scrolling behavior.

### Description of Change

This change ensures proper handler initialization for views created from
a `DataTemplate`, allowing accurate size measurement and proper layout
behavior.

### Issues Fixed

Fixes dotnet#28101 

**Tested the behaviour in the following platforms**

- [x] Android (primary - bug in Android only)
- [ ]  Windows
- [ ]  iOS
- [ ] Mac

### Output 

|Before|After|
|--|--|
|<video
src="https://github.com/user-attachments/assets/314539cc-9307-4cf1-aa8e-566e3cb0ef1a">|
<video
src="https://github.com/user-attachments/assets/18004a13-e6b7-4331-ba3a-ca1f017ca6a8">|

---------
Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
sheiksyedm pushed a commit that referenced this pull request Apr 4, 2026
…View with EmptyView (#28107)

<!-- 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)](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!
### RootCause

When using a `DataTemplate` for headers or footers in a
`CollectionView`, the generated views lack proper handler initialization
by default. This results in incorrect size calculations, causing the
header or footer to have a measured size of zero (0), which affects
layout rendering and scrolling behavior.

### Description of Change

This change ensures proper handler initialization for views created from
a `DataTemplate`, allowing accurate size measurement and proper layout
behavior.

### Issues Fixed

Fixes #28101 

**Tested the behaviour in the following platforms**

- [x] Android (primary - bug in Android only)
- [ ]  Windows
- [ ]  iOS
- [ ] Mac

### Output 

|Before|After|
|--|--|
|<video
src="https://github.com/user-attachments/assets/314539cc-9307-4cf1-aa8e-566e3cb0ef1a">|
<video
src="https://github.com/user-attachments/assets/18004a13-e6b7-4331-ba3a-ca1f017ca6a8">|

---------
Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-collectionview CollectionView, CarouselView, IndicatorView community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CollectionView Footer Becomes Scrollable When EmptyView is Active on Android

10 participants