Skip to content

Fix MAUIG2045 false positive with x:Reference source in DataTemplate#34501

Merged
StephaneDelcroix merged 1 commit intomainfrom
34490-018a
Mar 18, 2026
Merged

Fix MAUIG2045 false positive with x:Reference source in DataTemplate#34501
StephaneDelcroix merged 1 commit intomainfrom
34490-018a

Conversation

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

Description

Fixes #34490

When Source={x:Reference} is used in a binding inside a DataTemplate, the XAML source generator incorrectly resolves the Path against the DataTemplate's x:DataType instead of the referenced element's type. This causes a false MAUIG2045 warning for patterns like Path=BindingContext.SelectItemCommand.

Example triggering the false positive

<DataTemplate x:DataType="models:ItemModel">
    <Button Command="{Binding Source={x:Reference PageRoot},
                             Path=BindingContext.SelectItemCommand}" />
</DataTemplate>

The source generator tries to find BindingContext on ItemModel (the DataTemplate's x:DataType) instead of recognizing that the binding source is the referenced element.

Root Cause

HasRelativeSourceBinding() in KnownMarkups.cs only checked for RelativeSourceExtension/RelativeSource when deciding whether to skip compiled binding generation. It did not account for ReferenceExtension/Reference (x:Reference), so bindings with Source={x:Reference} were still compiled against the current x:DataType scope.

Fix

Extended HasRelativeSourceBinding() to also detect ReferenceExtension and Reference (the two forms of x:Reference). When detected, the source generator skips compiled binding and falls back to runtime binding — the same behavior already used for RelativeSource bindings.

Tests

  • SourceGen.UnitTests: BindingWithXReferenceSourceInDataTemplate_DoesNotReportPropertyNotFound — verifies no MAUIG2045 diagnostic is emitted
  • Xaml.UnitTests: Maui34490 — XAML page reproducing the exact issue scenario, tested across all inflators (Runtime, XamlC, SourceGen)

Copilot AI review requested due to automatic review settings March 16, 2026 18:48
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 16, 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 -- 34501

Or

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

@StephaneDelcroix
Copy link
Copy Markdown
Contributor Author

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

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

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 addresses a MAUIG2045 false positive in the XAML source generator when a binding inside a DataTemplate uses an explicit Source={x:Reference ...}. The fix updates the source generator’s decision logic so it won’t attempt to compile bindings against the DataTemplate’s x:DataType when the binding source is explicitly overridden via x:Reference, preventing incorrect “property not found” diagnostics.

Changes:

  • Update SourceGen binding analysis to treat Source={x:Reference ...} similarly to RelativeSource for compiled-binding eligibility.
  • Add a SourceGen unit test asserting MAUIG2045 is not emitted for the reported scenario.
  • Add a Xaml.UnitTests issue reproduction page (Maui34490) covering the same binding pattern across inflators.

Reviewed changes

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

File Description
src/Controls/src/SourceGen/KnownMarkups.cs Extends HasRelativeSourceBinding to detect ReferenceExtension / Reference so compiled binding is skipped when Source is x:Reference.
src/Controls/tests/SourceGen.UnitTests/BindingDiagnosticsTests.cs Adds regression test ensuring MAUIG2045 is not reported for x:Reference source in a DataTemplate.
src/Controls/tests/Xaml.UnitTests/Issues/Maui34490.xaml Adds issue XAML reproducing the binding pattern (x:Reference to page root inside DataTemplate).
src/Controls/tests/Xaml.UnitTests/Issues/Maui34490.xaml.cs Adds issue test; includes a SourceGen diagnostic assertion path for MAUIG2045.

@StephaneDelcroix
Copy link
Copy Markdown
Contributor Author

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

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@StephaneDelcroix StephaneDelcroix force-pushed the 34490-018a branch 2 times, most recently from c03565d to 86dc2db Compare March 16, 2026 20:34
@StephaneDelcroix
Copy link
Copy Markdown
Contributor Author

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

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@StephaneDelcroix
Copy link
Copy Markdown
Contributor Author

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

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

Copy link
Copy Markdown
Member

@PureWeen PureWeen left a comment

Choose a reason for hiding this comment

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

Re-Review: New x:Reference Type Resolution Approach

The new commit takes a fundamentally better approach (resolve x:Reference target types and compile against them), but introduces a build-breaking regression confirmed by CI.


Previous Findings Status

  • Finding 1 (x:DataType regression): ✅ FIXED — x:Reference bindings are now compiled against the resolved type instead of being blanket-skipped.
  • Finding 2 (SourceGen page instantiation): ✅ FIXED — SourceGen branch no longer skips page instantiation in Maui34490.xaml.cs.
  • Finding 3 (inaccurate comment): ✅ FIXED — Updated comment accurately describes the three-way behavior.
  • Finding 4 (namespace URI check): ⚠️ STILL PRESENT (pre-existing) — TryResolveXReferenceSourceType checks XmlType.Name without verifying NamespaceUri, same pattern as HasRelativeSourceBinding.

New Findings

[BUG — CI-BREAKING] BindingContext.Property path emits MAUIG2045 → build error
KnownMarkups.csTryResolveXReferenceSourceType + TryParsePath

When Source is {x:Reference SomePage} and Path is BindingContext.SomeCommand:

  1. TryResolveXReferenceSourceType resolves SomePageContentPage
  2. TryParsePath walks: BindingContext found on BindableObject (typed as object) ✅
  3. SomeCommand not found on object → emits MAUIG2045 unconditionally → returns false
  4. Falls back to runtime binding (correct) — but the diagnostic is already emitted
  5. Directory.Build.props sets TreatWarningsAsErrors=truebuild error

Before this PR: these bindings never entered compilation (no x:DataTypeTryGetXDataType returned null → no compilation → no warning).
After this PR: TryResolveXReferenceSourceType provides a type → compilation is attempted → MAUIG2045 emitted on the object hop.

CI confirms this — all 3 failing jobs (Build Sample App, Build Sample App (CoreCLR), Build Sample App (Material3)) fail with 4 unique MAUIG2045 errors:

File Path Property not found on object
Issue8295.xaml:13,25 BindingContext.TbGlyph TbGlyph
Issue1455.xaml:16,29 BindingContext.IsContextActionsLegacyModeEnabled IsContextActionsLegacyModeEnabled
Issue6932_emptyviewtemplate.xaml:16 BindingContext.EmptyTemplateAutomationId EmptyTemplateAutomationId
Issue2951.xaml:17 BindingContext.ButtonTapped ButtonTapped

Additionally, 9+ files in Controls.Sample use the same pattern (SwipeView galleries with BindingContext.FavouriteCommand, BindingContext.DeleteCommand, etc.) and will break when those builds run.

Root cause: TryParsePath emits diagnostics unconditionally. For x:DataType-driven compilation, this makes sense (developer explicitly declared the type). For x:Reference-driven compilation, this is a false positive — the generator is opportunistically trying to compile what was always a runtime binding.

Suggested fix: When the data type was resolved via TryResolveXReferenceSourceType (not TryGetXDataType), either:

  1. Suppress MAUIG2045 by passing a flag to TryCompileBinding/TryParsePath to skip the diagnostic
  2. Check if the first path segment resolves to object and bail before attempting further compilation
  3. Wrap the compilation attempt and discard any diagnostics on failure (treat as "best effort")

[OBSERVATION] Wider behavioral change for all x:Reference bindings

The PR description focuses on DataTemplate scenarios, but the change affects all {Binding Source={x:Reference X}, Path=P} patterns globally. There are 46 such bindings in TestCases.HostApp and 135 in Controls.Sample. Most will compile successfully (e.g., {Binding Source={x:Reference slider}, Path=Value} → Slider.Value exists), but the BindingContext.Property subset will break. This broader scope should be documented in the PR description.


Summary

The approach is sound — resolving x:Reference types for compiled bindings is the right direction. The blocking issue is that TryParsePath unconditionally emits MAUIG2045 when it hits an object type in the path chain, and this triggers build failures in TreatWarningsAsErrors projects. Once that diagnostic emission is gated for x:Reference-resolved bindings, the CI failures should clear.

@StephaneDelcroix
Copy link
Copy Markdown
Contributor Author

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

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@StephaneDelcroix
Copy link
Copy Markdown
Contributor Author

/azp run maui-pr

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@StephaneDelcroix
Copy link
Copy Markdown
Contributor Author

/azp run maui-pr

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

When Source={x:Reference} is used in a binding inside a DataTemplate,
the source generator incorrectly resolves the Path against the
DataTemplate's x:DataType instead of the referenced element's type.

The fix resolves the x:Reference target's type via namescope lookup
and compiles the binding path against that type. For example,
Source={x:Reference PageRoot} with Path=BindingContext.SelectItemCommand
now resolves against ContentPage (the referenced element) instead of
ItemModel (the DataTemplate's x:DataType).

Fixes #34490

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

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

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@github-project-automation github-project-automation bot moved this from Todo to Approved in MAUI SDK Ongoing Mar 18, 2026
@StephaneDelcroix StephaneDelcroix merged commit bd4b125 into main Mar 18, 2026
163 checks passed
@StephaneDelcroix StephaneDelcroix deleted the 34490-018a branch March 18, 2026 09:19
@github-project-automation github-project-automation bot moved this from Approved to Done in MAUI SDK Ongoing Mar 18, 2026
jfversluis pushed a commit that referenced this pull request Mar 18, 2026
… source in DataTemplate (#34525)

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

Backport of #34501 to `release/10.0.1xx-sr5`.

When a binding uses `Source={x:Reference}`, the source generator was
incorrectly validating the binding path against `x:DataType` instead of
the referenced element, producing a false MAUIG2045 warning. This fix
detects explicit binding sources (both `RelativeSource` and
`x:Reference`) and skips compilation, falling back to runtime binding.

Fixes #34490

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
KarthikRajaKalaimani pushed a commit to KarthikRajaKalaimani/maui that referenced this pull request Mar 30, 2026
…otnet#34501)

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

Fixes dotnet#34490

When `Source={x:Reference}` is used in a binding inside a
`DataTemplate`, the XAML source generator incorrectly resolves the
`Path` against the DataTemplate's `x:DataType` instead of the referenced
element's type. This causes a false **MAUIG2045** warning for patterns
like `Path=BindingContext.SelectItemCommand`.

### Example triggering the false positive

```xml
<DataTemplate x:DataType="models:ItemModel">
    <Button Command="{Binding Source={x:Reference PageRoot},
                             Path=BindingContext.SelectItemCommand}" />
</DataTemplate>
```

The source generator tries to find `BindingContext` on `ItemModel` (the
DataTemplate's `x:DataType`) instead of recognizing that the binding
source is the referenced element.

## Root Cause

`HasRelativeSourceBinding()` in `KnownMarkups.cs` only checked for
`RelativeSourceExtension`/`RelativeSource` when deciding whether to skip
compiled binding generation. It did not account for
`ReferenceExtension`/`Reference` (`x:Reference`), so bindings with
`Source={x:Reference}` were still compiled against the current
`x:DataType` scope.

## Fix

Extended `HasRelativeSourceBinding()` to also detect
`ReferenceExtension` and `Reference` (the two forms of `x:Reference`).
When detected, the source generator skips compiled binding and falls
back to runtime binding — the same behavior already used for
`RelativeSource` bindings.

## Tests

- **SourceGen.UnitTests**:
`BindingWithXReferenceSourceInDataTemplate_DoesNotReportPropertyNotFound`
— verifies no MAUIG2045 diagnostic is emitted
- **Xaml.UnitTests**: `Maui34490` — XAML page reproducing the exact
issue scenario, tested across all inflators (Runtime, XamlC, SourceGen)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
StephaneDelcroix added a commit that referenced this pull request Apr 1, 2026
…34513)

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

Follow-up to #34501 (which targets `main` with a minimal fix).

This PR enhances x:Reference binding compilation for `net11.0` by
**resolving the referenced element's type** and compiling the binding
against it, instead of skipping compilation entirely.

### What it does

When a binding uses `Source={x:Reference Name}`, the source generator
now:

1. **Walks namescopes** to find the referenced element's type (e.g.,
`ContentPage` for `x:Reference PageRoot`, `Label` for `x:Reference
StatusLabel`)
2. **Compiles the binding** against the resolved type when the path is
fully resolvable (e.g., `Path=Text` on a `Label`)
3. **Falls back silently** to runtime binding when the path can't be
resolved (e.g., `Path=BindingContext.SelectItemCommand` where
`BindingContext` is `object`)

### Key design decision: `out Diagnostic?` on `TryParsePath`

The MAUIG2045 ("property not found") diagnostic is now returned as an
`out` parameter from `TryParsePath`/`TryCompileBinding` instead of being
emitted directly. This lets the caller decide:
- **x:DataType bindings**: emit MAUIG2045 as before (no behavior change)
- **x:Reference bindings**: suppress MAUIG2045 and fall back to runtime
(these were never compiled before, so a new warning would be a
regression)

### Tests added

- `BindingWithXReferenceSourceInDataTemplate_DoesNotReportFalsePositive`
— verifies no false MAUIG2045 for `Path=BindingContext.X`
- `BindingWithXReferenceToNonRootElement_ResolvesCorrectType` — verifies
`Path=Text` against a referenced `Label` compiles with no warnings
- `Maui34490.xaml` — XAML unit test reproducing the original issue
- Updated `Gh3606` test — binding to `Content` via x:Reference now
compiles

Fixes #34490

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

MAUIG2045 false positive when binding to parent BindingContext via x:Reference inside DataTemplate

4 participants