Skip to content

[Windows] - Fix Grid layout not updating when Row/Column changed dynamically#30206

Open
prakashKannanSf3972 wants to merge 7 commits intodotnet:mainfrom
prakashKannanSf3972:fix-20404
Open

[Windows] - Fix Grid layout not updating when Row/Column changed dynamically#30206
prakashKannanSf3972 wants to merge 7 commits intodotnet:mainfrom
prakashKannanSf3972:fix-20404

Conversation

@prakashKannanSf3972
Copy link
Copy Markdown
Contributor

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

  • When Grid.Row or Grid.Column properties are updated on a Grid element nested within another Grid, the current implementation only invalidates the element itself and does not propagate the invalidation to its parent. As a result, the parent layout is not re-measured or arranged correctly, leading to inaccurate or incomplete rendering.

Description of Change

  • Improved parent layout invalidation for Grid on Windows to ensure UI updates correctly when Grid.Row or Grid.Column properties change.

Issues Fixed

Fixes #20404

Tested the behaviour in the following platforms

  • Android
  • Windows
  • iOS
  • Mac

Output

Before After
BeforeFix_Grid.mp4
AfterFix_Grid.mp4

@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Hey there @@prakashKannanSf3972! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service dotnet-policy-service bot added community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration labels Jun 25, 2025
@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

/azp run MAUI-UITests-public

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@prakashKannanSf3972 prakashKannanSf3972 marked this pull request as ready for review June 27, 2025 07:02
Copilot AI review requested due to automatic review settings June 27, 2025 07:02
@prakashKannanSf3972 prakashKannanSf3972 requested a review from a team as a code owner June 27, 2025 07:02
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.

Pull Request Overview

This PR ensures that dynamic changes to Grid.Row and Grid.Column on Windows correctly invalidate the parent layout so the UI updates without requiring a window resize.

  • Added a UI sample page in the HostApp for toggling row/column at runtime.
  • Added a cross-platform UI test in TestCases.Shared.Tests to verify dynamic grid updates.
  • Updated Grid.cs to propagate measure invalidation to the parent grid on Windows.

Reviewed Changes

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

File Description
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue20404.cs New UITest verifying dynamic row/column toggles trigger layout updates.
src/Controls/tests/TestCases.HostApp/Issues/Issue20404.cs New sample page with buttons to toggle grid row/column dynamically.
src/Controls/src/Core/Layout/Grid.cs Updated Invalidate method to explicitly invalidate parent grid on Windows.

@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-gate-failed AI could not verify tests catch the bug s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Mar 21, 2026
@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented Mar 21, 2026

/azp run maui-pr-uitests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Could you please review the AI's summary?

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 25, 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 -- 30206

Or

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

@Dhivya-SF4094
Copy link
Copy Markdown
Contributor

Could you please review the AI's summary?

Validated the AI summary and addressed the concerns accordingly.
Note: The issue linked to this PR has been closed as not planned

@sheiksyedm
Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests , maui-pr-devicetests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 27, 2026

🚦 Gate — Test Verification

📊 Expand Full Gate5e4a947 · Addressed AI summary

Gate Result: ❌ FAILED

Platform: WINDOWS

Tests Detected

# Type Test Name Filter
1 UITest Issue20404 Issue20404

Verification

Step Expected Actual Result
Without fix FAIL FAIL
With fix PASS FAIL

Details

  • Failed: DynamicGridRowColumnChangeShouldInvalidate [3 s]
  • 📋 Error: VisualTestUtils.VisualTestFailedException :
    Snapshot different than baseline: AfterGridRowToggled.png (36.09% difference)
    If the correct baseline has changed (this isn't a a bug), then update the b...
  • Failed: DynamicGridRowColumnChangeShouldInvalidate [2 s]
  • 📋 Error: VisualTestUtils.VisualTestFailedException :
    Snapshot different than baseline: AfterGridRowToggled.png (6.51% difference)
    If the correct baseline has changed (this isn't a a bug), then update the ba...

Fix Files Reverted

  • eng/pipelines/ci-copilot.yml
  • src/Controls/src/Core/Layout/Grid.cs

Base Branch: main | Merge Base: 720a9d4


@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 27, 2026

🤖 AI Summary

📊 Expand Full Review5e4a947 · Addressed AI summary
🔍 Pre-Flight — Context & Validation

Issue: #20404 - Changing Grid.Row does not update layout until window is resized
PR: #30206 - [Windows] Fix Grid layout not updating when Row/Column changed dynamically
Platforms Affected: Windows (WinUI) — issue is Windows-specific per labels; root cause (logic asymmetry) is cross-platform
Files Changed: 1 implementation (Grid.cs), 1 test page (Issue20404.cs), 1 test class (Issue20404.cs), 8 snapshot PNGs

Key Findings

  • Root cause: Grid.Invalidate() has an else if asymmetry. When bindable is Grid, it calls grid.InvalidateMeasure() on the child but never propagates to the parent. The else if for non-Grid elements correctly calls parentGrid.InvalidateMeasure() — but this branch is never reached when the child IS a Grid (since Grid is also Element, the else if is mutually exclusive).
  • PR's fix: Adds #if WINDOWS block inside the if (bindable is Grid) branch, calling containerGrid.InvalidateMeasure() + return if parent is Grid. Also includes a return statement that is logically harmless but confusing.
  • Issues with PR's fix:
    1. #if WINDOWS compile-time guard for a logical inconsistency present on all platforms
    2. The return exits the method early (harmless now, but fragile)
    3. Only handles Grid-in-Grid; a Grid nested in StackLayout is still affected
    4. Snapshot PNG baselines captured locally → don't match CI rendering
  • Gate FAILED: DynamicGridRowColumnChangeShouldInvalidate fails — screenshot comparison fails with 36.09% / 6.51% difference on snapshots that don't match CI.
  • Prior agent review found: Full 4-phase review already performed (see MauiBot comment). Candidate Update README.md #5 (change else ifif) found to be the cleanest fix; Candidate Update README.md #2 (same Grid.cs fix + GetRect() assertions) also passed.
  • Inline review comment: Copilot reviewer suggested OperatingSystem.IsWindows() runtime check instead of #if WINDOWS (marked resolved but concern not fully addressed).
  • Issue closed as "not planned" — PR is fixing a bug on the issue closed before it was opened.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #30206 #if WINDOWS block: containerGrid.InvalidateMeasure() + return when child is Grid with Grid parent ❌ FAILED (Gate) Grid.cs, 8 snapshot PNGs Snapshot mismatch in CI; fix too narrow; #if WINDOWS unnecessary

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) Remove else from else if in Grid.Invalidate() standalone if; GetRect() test assertions PASS Grid.cs, Issue20404.cs Most minimal 1-char change; cross-platform; no #if WINDOWS
2 try-fix (claude-sonnet-4.6) Add if (grid.Parent is Grid parentGrid) { parentGrid.InvalidateMeasure(); } inside if (bindable is Grid) block; kept else if; GetRect() assertions PASS Grid.cs, Issue20404.cs Cross-platform; preserves existing structure; adds minimal parent check
3 try-fix (gpt-5.3-codex) Walk full ancestor chain invalidating ALL ancestor Grids; GetRect() assertions PASS Grid.cs, Issue20404.cs More thorough but overkill; handles deeply nested Grids
4 try-fix (gpt-5.1-codex) Invalidate nearest Layout parent (not just Grid parent); covers non-Grid parents too; GetRect() assertions PASS Grid.cs, Issue20404.cs Broader fix; handles Grid-in-StackLayout-in-Grid case
5 try-fix (claude-sonnet-4.6) Override OnChildAdded/OnChildRemoved to subscribe to PropertyChanged; call InvalidateMeasure() on parent Grid PASS Grid.cs, Issue20404.cs, 2xPublicAPI.Unshipped.txt Different paradigm (parent observes children); adds public API surface; most complex
PR PR #30206 #if WINDOWS block: containerGrid.InvalidateMeasure() + return when child is Grid with Grid parent FAILED (Gate) Grid.cs, 8 snapshot PNGs Snapshot mismatch in CI; fix too narrow; #if WINDOWS unnecessary

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 Yes Fix in Windows LayoutHandler/LayoutPanel at platform boundary
claude-sonnet-4.6 2 Yes Override OnChildPropertyChanged in Grid became Attempt 5
gpt-5.3-codex 2 Yes Force Windows arrange invalidation via InvalidateArrange() on parent
gpt-5.1-codex 2 Yes Platform-specific handler hook for Windows native panel invalidation
claude-opus-4.6 3 No NO NEW IDEAS "Attempt 1 is the minimal, correct fix"
claude-sonnet-4.6 3 Yes Override InvalidateMeasure() on Grid to chain to Parent
gpt-5.3-codex 3 Yes Layout-version invalidation + InvalidateArrange() targeting stale arrange cache
gpt-5.1-codex 3 Yes Hook into attached BindableProperty changed callback to walk up immediately

Exhausted: Yes (max 3 rounds reached)
Selected Fix: Candidate #1 (remove else from else if) Most minimal fix: 1-character change in Grid.cs. Directly fixes the logical root cause (decouples the two independent checks). Cross-platform, no #if WINDOWS, no added public API surface, no event subscriptions. Test: replace VerifyScreenshot with GetRect() position assertions.


📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #20404, Windows-only layout staleness bug when Grid.Row/Column set dynamically on child Grid
Gate ❌ FAILED Windows — test fails even with PR's fix (snapshot PNG baseline mismatch: 36.09% / 6.51% diff)
Try-Fix ✅ COMPLETE 5 attempts, all 5 passing; better fix found (Candidate #1)
Report ✅ COMPLETE

Summary

PR #30206 fixes a real, reproducible bug: calling Grid.SetRow()/Grid.SetColumn() dynamically on a child Grid element leaves the parent Grid's layout stale on Windows (WinUI) until a window resize forces re-measurement. The PR's fix is on the right track but uses unnecessary #if WINDOWS compile-time guards, includes a confusing return statement, and ships snapshot PNG baselines captured on the author's machine that don't match the CI rendering environment — causing the gate to fail even with the fix applied.

Try-Fix exploration found 5 independent passing fixes. The simplest and best is Candidate #1: remove else from else if in Grid.Invalidate(), making both checks independent. This is a 1-character change that directly fixes the logical root cause, is cross-platform, and requires no #if WINDOWS guard. The test must also be updated to use GetRect() position assertions instead of VerifyScreenshot().

Root Cause

Grid.Invalidate() has a structural asymmetry using else if:

if (bindable is Grid grid)
{
    grid.InvalidateMeasure();   // only child is invalidated
}
else if (bindable is Element element && element.Parent is Grid parentGrid)
{
    parentGrid.InvalidateMeasure();  // never reached when child IS a Grid!
}

Since Grid is also an Element, the else if condition is mutually exclusive with the first if. When a child is a Grid, only that child gets InvalidateMeasure() — the parent Grid never does. On Android/iOS, the native layout system propagates invalidation upward automatically, masking this bug. On Windows/WinUI it doesn't, so the parent Grid never re-measures.

Fix Quality

PR's fix — ❌ FAILED gate:

  • #if WINDOWS compile-time guard for a cross-platform logical inconsistency — unnecessary
  • return exits the Invalidate method early (harmless today, fragile for future changes)
  • Only handles the Grid-in-Grid case; a Grid nested in other layout types is unaffected
  • Snapshot PNG baselines were captured on author's machine; don't match CI environment

Recommended fix — Candidate #1 (✅ PASS):

src/Controls/src/Core/Layout/Grid.cs:

-        else if (bindable is Element element && element.Parent is Grid parentGrid)
+
+        if (bindable is Element element && element.Parent is Grid parentGrid)

src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue20404.cs: Replace VerifyScreenshot() calls with GetRect() position assertions on DynamicLabel:

// After ToggleRow: DynamicGrid moves to row 0 → label Y should decrease
var rectBefore = App.WaitForElement("DynamicLabel").GetRect();
App.Tap("ToggleRowButton");
var rectAfter = App.WaitForElement("DynamicLabel").GetRect();
Assert.That(rectAfter.Y, Is.LessThan(rectBefore.Y));

Benefits:

  • ✅ 1-character change in Grid.cs (else removed) — minimal, elegant
  • ✅ Cross-platform — no #if WINDOWS, no OperatingSystem.IsWindows() check
  • ✅ Fixes the logical root cause (decouples the two independent checks)
  • ✅ Harmless on other platforms (extra InvalidateMeasure() on parent is a no-op when platform auto-propagates)
  • ✅ Test uses GetRect() movement assertions — CI-environment-independent, no PNG baselines needed

Required Changes

  1. src/Controls/src/Core/Layout/Grid.cs — Change else if to if (remove else)
  2. src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue20404.cs — Replace VerifyScreenshot with GetRect() position assertions
  3. Remove all snapshot PNG files (AfterGridRowToggled.png, AfterGridColumnToggled.png across Android/Mac/WinUI/iOS test projects) — unused when VerifyScreenshot is removed and incorrect anyway

@MauiBot MauiBot added s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) s/agent-changes-requested AI agent recommends changes - found a better alternative or issues and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) labels Mar 27, 2026
Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Test is failing; could you please verify?

Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Could you please check the AI's summary?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community ✨ Community Contribution layout-grid partner/syncfusion Issues / PR's with Syncfusion collaboration platform/windows s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR s/agent-gate-failed AI could not verify tests catch the bug 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.

Changing Grid.Row does not update layout until window is resized

10 participants