Skip to content

Optimize DataTemplateExtension as KnownMarkup in source generator#32761

Merged
StephaneDelcroix merged 1 commit intomainfrom
datatemplate-knownmarkup
Nov 20, 2025
Merged

Optimize DataTemplateExtension as KnownMarkup in source generator#32761
StephaneDelcroix merged 1 commit intomainfrom
datatemplate-knownmarkup

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

This PR implements DataTemplateExtension as a KnownMarkup in the XAML source generator, reducing generated code size by ~95% and improving performance through direct constructor calls instead of reflection-based ProvideValue.

Changes Made

Source Generator Implementation

KnownMarkups.cs:

  • Added ProvideValueForDataTemplateExtension method
  • Resolves TypeName to Type at compile time
  • Generates direct new DataTemplate(typeof(...)) constructor calls

NodeSGExtensions.cs:

  • Registered DataTemplateExtension in GetKnownEarlyMarkupExtensions
  • Classified as "early" since it only needs string TypeName input

Unit Tests

DataTemplateMarkupExtension.cs:

  • DataTemplateMarkupExtensionWithType: Tests with custom ViewCell class
  • DataTemplateMarkupExtensionInListView: Tests with built-in Label control
  • Both validate the simplified generated code

Code Generation Comparison

Before (ProvideValue pattern - ~40 lines)

var dataTemplateExtension = new global::Microsoft.Maui.Controls.Xaml.DataTemplateExtension();
dataTemplateExtension.TypeName = "local:CustomCell";
var xamlServiceProvider = new global::Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider(__root);
var iProvideValueTarget = new global::Microsoft.Maui.Controls.Xaml.Internals.SimpleValueTargetProvider(
    new object?[] {collectionView, __root},
    global::Microsoft.Maui.Controls.ItemsView.ItemTemplateProperty,
    new [] { iNameScope },
    __root);
xamlServiceProvider.Add(typeof(global::Microsoft.Maui.Controls.Xaml.IReferenceProvider), iProvideValueTarget);
xamlServiceProvider.Add(typeof(global::Microsoft.Maui.Controls.Xaml.IProvideValueTarget), iProvideValueTarget);
var xmlNamespaceResolver = new global::Microsoft.Maui.Controls.Xaml.Internals.XmlNamespaceResolver();
xmlNamespaceResolver.Add("__f__", "http://schemas.microsoft.com/dotnet/2021/maui");
xmlNamespaceResolver.Add("__g__", "http://schemas.microsoft.com/dotnet/maui/global");
xmlNamespaceResolver.Add("", "http://schemas.microsoft.com/dotnet/2021/maui");
xmlNamespaceResolver.Add("x", "http://schemas.microsoft.com/winfx/2009/xaml");
xmlNamespaceResolver.Add("local", "clr-namespace:Test");
xamlServiceProvider.Add(typeof(global::Microsoft.Maui.Controls.Xaml.IXamlTypeResolver), new global::Microsoft.Maui.Controls.Xaml.Internals.XamlTypeResolver(xmlNamespaceResolver, typeof(global::Test.TestPage).Assembly));
xamlServiceProvider.Add(typeof(global::Microsoft.Maui.Controls.Xaml.IXmlLineInfoProvider), new global::Microsoft.Maui.Controls.Xaml.Internals.XmlLineInfoProvider(new global::Microsoft.Maui.Controls.Xaml.XmlLineInfo(7, 18)));
var dataTemplate = (global::Microsoft.Maui.Controls.DataTemplate)((global::Microsoft.Maui.Controls.Xaml.IMarkupExtension<global::Microsoft.Maui.Controls.DataTemplate>)dataTemplateExtension).ProvideValue(xamlServiceProvider);
collectionView.SetValue(global::Microsoft.Maui.Controls.ItemsView.ItemTemplateProperty, dataTemplate);

After (KnownMarkup - ~2 lines)

var dataTemplateExtension = new global::Microsoft.Maui.Controls.DataTemplate(typeof(global::Test.CustomCell));
collectionView.SetValue(global::Microsoft.Maui.Controls.ItemsView.ItemTemplateProperty, dataTemplateExtension);

Benefits

  1. Simpler Generated Code: ~95% reduction in code size per DataTemplate usage
  2. Better Performance: Direct constructor calls instead of reflection-based ProvideValue
  3. Compile-Time Type Resolution: Type errors caught during compilation
  4. Better Code Quality: Easier to read and debug generated code
  5. Consistency: Follows the same pattern as TypeExtension, StaticExtension, etc.

Testing

✅ All 75 SourceGen unit tests pass
✅ 2 new DataTemplate-specific tests added and passing
✅ No regressions in existing functionality

Issues Fixed

Fixes #32760

…ation

- Add ProvideValueForDataTemplateExtension to KnownMarkups.cs
- Register DataTemplateExtension in GetKnownEarlyMarkupExtensions
- Create comprehensive unit tests for DataTemplate markup extension
- Generate direct DataTemplate constructor calls instead of ProvideValue pattern
- Reduces generated code from ~40 lines to ~2 lines per usage
- All 75 SourceGen unit tests pass
Copilot AI review requested due to automatic review settings November 20, 2025 09:02
@StephaneDelcroix StephaneDelcroix added area-xaml XAML, CSS, Triggers, Behaviors xsg Xaml sourceGen labels Nov 20, 2025
@StephaneDelcroix StephaneDelcroix added this to the .NET 10.0 SR2 milestone Nov 20, 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 successfully optimizes DataTemplateExtension by implementing it as a KnownMarkup in the XAML source generator, achieving ~95% code reduction and eliminating reflection overhead. The implementation follows the established pattern used by TypeExtension and other early markup extensions.

Key Changes

  • Added ProvideValueForDataTemplateExtension method that resolves type names at compile-time and generates direct DataTemplate constructor calls
  • Registered DataTemplateExtension as an early markup extension alongside TypeExtension, StaticExtension, etc.
  • Added comprehensive unit tests validating the optimized code generation for both custom and built-in types

Reviewed Changes

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

File Description
src/Controls/tests/SourceGen.UnitTests/InitializeComponent/DataTemplateMarkupExtension.cs New test file with two tests covering DataTemplate usage with custom ViewCell types and built-in Label controls, validating simplified generated code
src/Controls/src/SourceGen/NodeSGExtensions.cs Registration of DataTemplateExtension in GetKnownEarlyMarkupExtensions dictionary to enable compile-time optimization
src/Controls/src/SourceGen/KnownMarkups.cs Core implementation that resolves TypeName to Type at compile-time and generates direct constructor calls, following TypeExtension pattern with proper error handling and fallback logic

@StephaneDelcroix
Copy link
Contributor Author

/azp run MAUI-UITests-public

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@StephaneDelcroix StephaneDelcroix merged commit 4667153 into main Nov 20, 2025
165 of 169 checks passed
@StephaneDelcroix StephaneDelcroix deleted the datatemplate-knownmarkup branch November 20, 2025 20:19
@github-actions github-actions bot locked and limited conversation to collaborators Dec 21, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-xaml XAML, CSS, Triggers, Behaviors xsg Xaml sourceGen

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Optimize DataTemplateExtension as KnownMarkup in source generator

3 participants