Skip to content

Conversation

@StephaneDelcroix
Copy link
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 #13856

Problem

Using x:DataType with a binding to Dictionary<CustomEnum, object> like {Binding UserSettings[TBD]} caused a NullReferenceException at compile time in XamlC.

Root Cause

XamlC's SetPropertiesVisitor.cs only supported int, string, and object indexer parameter types. When encountering an enum type, it failed to find a matching indexer and returned null, causing a NullReferenceException when trying to access properties on the null indexer.

Solution

  • XamlC (SetPropertiesVisitor.cs): Added support for finding indexers with enum parameter types and emitting enum constant values via IL
  • SourceGen (CompiledBindingMarkup.cs): Added support for enum indexer parameter types in the binding path parser

Changes

SetPropertiesVisitor.cs

  • Added enum indexer detection when looking for property indexers
  • Updated type validation to allow enum indexer types
  • Added code to emit enum constant values as IL instructions

CompiledBindingMarkup.cs

  • Added enum indexer support in TryParsePath method
  • When an enum indexer is found, generates the fully qualified enum member reference

Test Fixes

  • Fixed pre-existing test failure in Maui32879Tests.cs (updated expected output to include #pragma warning disable CS0219)

Tests Added

  • Maui13856.xaml + Maui13856.xaml.cs - XamlC unit test that verifies compilation succeeds
  • Maui13856Tests.cs - SourceGen unit test that verifies no errors are generated

Test Results

  • All 117 SourceGen.UnitTests pass
  • All Xaml.UnitTests binding and indexer tests pass

Copilot AI review requested due to automatic review settings November 29, 2025 06:21
Copilot finished reviewing on behalf of StephaneDelcroix November 29, 2025 06:24
@StephaneDelcroix StephaneDelcroix added this to the .NET 10.0 SR3 milestone Nov 29, 2025
Copy link
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 fixes a NullReferenceException that occurred when using x:DataType with bindings to Dictionary<Enum, object> properties in XAML. The issue was that both XamlC and SourceGen did not support enum types as dictionary indexer parameters, causing compilation failures.

Key Changes:

  • Added enum indexer parameter support to XamlC's SetPropertiesVisitor
  • Added enum indexer parameter support to SourceGen's CompiledBindingMarkup
  • Added comprehensive tests for both XamlC and SourceGen to prevent regression

Reviewed changes

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

Show a summary per file
File Description
src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs Added logic to detect enum indexer parameters, validate enum types, and emit enum constant values as IL instructions
src/Controls/src/SourceGen/CompiledBindingMarkup.cs Added logic to detect enum indexer parameters and generate fully qualified enum member references
src/Controls/tests/Xaml.UnitTests/Issues/Maui13856.xaml Test XAML file demonstrating Dictionary<Enum, object> binding with x:DataType
src/Controls/tests/Xaml.UnitTests/Issues/Maui13856.xaml.cs XamlC unit test verifying compilation succeeds without NullReferenceException
src/Controls/tests/SourceGen.UnitTests/Maui13856Tests.cs SourceGen unit test verifying no errors are generated for enum indexer bindings
src/Controls/tests/SourceGen.UnitTests/Maui32879Tests.cs Updated expected test output to include CS0219 pragma warning (pre-existing test fix)

if (enumMember != null)
{
index = $"{enumType.ToFQDisplayString()}.{indexArg}";
}
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

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

When an enum indexer is found but the enum member doesn't exist (enumMember is null), the code silently continues without updating the index variable. This means it will use the original indexArg string value instead of a fully qualified enum member reference, which could lead to incorrect code generation.

Consider adding an else clause to handle the case when the enum member is not found:

if (enumMember != null)
{
    index = $"{enumType.ToFQDisplayString()}.{indexArg}";
}
else
{
    // Log a diagnostic or return false to indicate parsing failure
    return false;
}
Suggested change
}
}
else
{
return false; // Enum member not found, fail parsing
}

Copilot uses AI. Check for mistakes.
@StephaneDelcroix StephaneDelcroix marked this pull request as draft November 29, 2025 06:40
@StephaneDelcroix StephaneDelcroix force-pushed the fix/13856-enum-dictionary-binding branch from d696d69 to 58e7fbd Compare November 29, 2025 06:46
@StephaneDelcroix StephaneDelcroix marked this pull request as ready for review November 29, 2025 06:47
@StephaneDelcroix StephaneDelcroix marked this pull request as draft November 29, 2025 06:57
…ith x:DataType

Fixes #13856

## Problem
Using  with a binding to  like  caused a NullReferenceException at compile time in XamlC.

## Solution
- **XamlC (SetPropertiesVisitor.cs)**: Added support for finding indexers with enum parameter types and emitting enum constant values via IL
- **SourceGen (CompiledBindingMarkup.cs)**: Added support for enum indexer parameter types in the binding path parser

## Changes
- Added enum indexer detection in XamlC's property digger
- Updated type validation to allow enum indexer types
- Added code to emit enum constant values as IL instructions
- Added enum indexer support in SourceGen's TryParsePath method
- Fixed pre-existing test failure in Maui32879Tests (unrelated pragma warning directive)

## Tests
- Added Maui13856.xaml unit test for XamlC compilation
- Added Maui13856Tests.cs for SourceGen validation
@StephaneDelcroix StephaneDelcroix force-pushed the fix/13856-enum-dictionary-binding branch from 58e7fbd to 6f6407e Compare November 29, 2025 08:08
@StephaneDelcroix StephaneDelcroix marked this pull request as ready for review November 29, 2025 08:15
@StephaneDelcroix StephaneDelcroix changed the title Fix NullReferenceException when binding to Dictionary<Enum, object> with x:DataType [C] Fix NullReferenceException when binding to Dictionary<Enum, object> with x:DataType Nov 29, 2025
Comment on lines +84 to +85
// Verify the binding path is in the generated code (even if using runtime binding fallback)
Assert.Contains("UserSettings[TBD]", generatedCode, System.StringComparison.Ordinal);
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this assert should be here. Ideally we'll drop the unnecessary markup extension instantiation at some point (#31614). I think this assert should look for .UserSettings[global::Test.UserSetting.TBD] instead.

Copy link
Member

Choose a reason for hiding this comment

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

(although that might currently fail due to #32905)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MAUI - XAML - Object reference not set to an instance of an object - reproducable, not same as #8249

3 participants