Skip to content

Add Avalonia.Controls.Maui support to templates#35950

Open
drasticactions wants to merge 3 commits into
dotnet:net11.0from
drasticactions:dev/timill/net11.0-avalonia-templates
Open

Add Avalonia.Controls.Maui support to templates#35950
drasticactions wants to merge 3 commits into
dotnet:net11.0from
drasticactions:dev/timill/net11.0-avalonia-templates

Conversation

@drasticactions

@drasticactions drasticactions commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

(I know it says "MAKE SURE THIS PR IS TARGETING MAIN" but since these packages only run in net11.0, I think it's right to target it there, since it shouldn't be in net10 builds, but we can always retarget it)

Description of Change

This PR adds the command --with-avalonia to the templates, which adds Avalonia.Controls.Maui desktop support the generated MAUI app.

app.mp4

This updates the basic template so it

  • Includes the Avalonia.Controls.Maui and Avalonia.Controls.Maui.Desktop nugets
  • Includes the net11.0 TFM as a deployable platform.
  • Updates the default Maui AppBuilder to include our handlers and embedded support.
public static class MauiProgram
{
	public static MauiApp CreateMauiApp(bool useSingleAppLifetime = false)
	{
		var builder = MauiApp.CreateBuilder();
		builder
			.UseMauiApp<App>()
#if !IOS && !MACCATALYST && !ANDROID && !WINDOWS
			.UseAvaloniaApp(useSingleAppLifetime)
#else
			.UseAvaloniaEmbedding<AvaloniaApp>()
#endif
			.ConfigureFonts(fonts =>
			{
				fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
				fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
			});

#if DEBUG
		builder.Logging.AddDebug();
#endif

		return builder.Build();
	}
}

useSingleAppLifetime is a parameter value that would get passed in from the Avalonia builder for which lifetime to use.
UseAvaloniaApp is where the Avalonia handlers are registered. It's if-defed out for the existing MAUI platforms so they render with native controls by default, since we're still working in this repo to enable running these handlers on those platforms.
UseAvaloniaEmbedding is enabled for those platforms to allow for "Embedded" Avalonia Maui controls and handlers, which is our existing Avalonia Maui Hybrid platform and lets you intergrate native and drawn controls together, with the native controls being the default.

This is our first run of getting a template change in, so we're keeping it simple.

  • It only edits the maui-mobile template for Desktop support. It doesn't change maui-blazor, which we don't support. I can add maui-multiplatform support if we want now, or that can be another PR, I don't have a preference.
  • This does not include support for the sample content template, since we would need to have Syncfusion support for that to work for our handlers. I would be happy to help with that effort.
  • This only implements it for Avalonia Desktop support. The browser support inside the template will come with a future PR, once we improve the accessibility story for WASM. You can, of course, add WASM support to your application yourself.
  • I used a wildcard for the version number in the template. I've aligned our versions on the .NET runtime version (So 11.0.0-...) but, of course, we can't align on MauiVersion. I can pin to a version if that's best.

@drasticactions drasticactions changed the title Dev/timill/net11.0 avalonia templates [test] Jun 16, 2026
@dotnet-policy-service dotnet-policy-service Bot added the community ✨ Community Contribution label Jun 16, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hey there @@drasticactions! 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

Copy link
Copy Markdown
Contributor

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

@drasticactions drasticactions changed the title [test] Add Avalonia.Controls.Maui support to templates Jun 16, 2026
@github-actions github-actions Bot added the area-templates Project templates, Item Templates for Blazor and MAUI label Jun 16, 2026
@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

🚀 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 -- 35950

Or

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

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

PR #35950 — Add Avalonia.Controls.Maui support to templates

Verdict: NEEDS_CHANGES (confidence: high). Nice addition — the new --with-avalonia option is structurally well-wired through template.json symbols, dotnetcli.host.json, the csproj (desktop head + Avalonia.Controls.Maui package refs), and there's an integration test. But the generated project doesn't compile in the Avalonia-on case.

Blocking (inline)

  • MauiProgram.cs:27UseAvaloniaEmbedding<AvaloniaApp>() references an undefined AvaloniaApp. On the mobile heads the embedding path needs an Avalonia Application type that the template never generates, so --with-avalonia produces a project that fails to build (CS0246). Generate the AvaloniaApp type as template content (or target an existing type). (3 models + code-confirmed.)

Suggestions (not blocking)

  • Integration test coverage (SimpleTemplateTest.cs): WithAvaloniaAddsHandlersAndDesktopHead currently mostly asserts generated content rather than building the Avalonia-on project. A build assertion would have caught the AvaloniaApp issue above — consider compiling the generated project with the option enabled. (gemini)
  • template.json version default (~line 202): the 11.0.0-preview.* floating range is reasonable for a preview-stage integration but pins consumers to whatever floats at restore time; consider a fixed version or document the intent. (opus-4.6)
  • template.json:199 parameter dataType — minor convention nit per gemini; worth a glance.

CI

Check Build/*Templates* integration legs once the AvaloniaApp issue is fixed — the template-generation tests are the relevant signal here.

Solid groundwork; the one real blocker is the missing AvaloniaApp in the generated output. Happy to re-review.

#if !IOS && !MACCATALYST && !ANDROID && !WINDOWS
.UseAvaloniaApp(useSingleAppLifetime)
#else
.UseAvaloniaEmbedding<AvaloniaApp>()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The generated project won't compile with --with-avalonia on the mobile heads — AvaloniaApp is undefined. On iOS/MacCatalyst/Android/Windows (the #else branch here) the template emits .UseAvaloniaEmbedding<AvaloniaApp>(), but AvaloniaApp is never generated anywhere in the template output — git grep finds it only on this line. (UseMauiApp<App>() at line 21 works because the template does generate App.) So a user who runs the template with the Avalonia option gets a project that fails to build with CS0246: The type or namespace name 'AvaloniaApp' could not be found. Either generate an AvaloniaApp (the Avalonia Application subclass that UseAvaloniaEmbedding<T> expects) as part of the template content, or point the embedding at the type that actually exists. The desktop branch (.UseAvaloniaApp(useSingleAppLifetime), line 25) doesn't need a type arg, which is why only the mobile/embedding path is broken. (Consensus: gpt-5.5 + gemini flagged this as an error; opus-4.6 as a warning; confirmed by code.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That should be fixed with 5f14dc8

It's an MSBuild parameter setting thing where it's correctly setting the flags for those platforms in source, but not from the nuget props. Setting it directly for everything will work (It's a setting since you could have your own Avalonia head written, but since this is a template app, you won't have that yet).

@kubaflo

kubaflo commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Re-review PR #35950 — Add Avalonia.Controls.Maui to templates (new head 5f14dc8)

Verdict: NEEDS_DISCUSSION (confidence: medium) — ⬆️ from NEEDS_CHANGES. Thanks for the fast turnaround on the AvaloniaApp issue.

The fix

The new commit adds (guarded by UseAvaloniaHandlers) to MauiApp.1.csproj:

<AvaloniaControlsMauiGenerateBootstrap>true</AvaloniaControlsMauiGenerateBootstrap>

This is the right mechanism: Avalonia.Controls.Maui's AvaloniaControlsMauiGenerateBootstrap MSBuild property auto-generates the Avalonia bootstrap class used for MAUI embedding, which is what MauiProgram.cs's .UseAvaloniaEmbedding<AvaloniaApp>() (line 27) references. So the previously-undefined AvaloniaApp is now expected to be source-generated by the package rather than missing — that addresses the compile-break I flagged.

What's left to confirm (why NEEDS_DISCUSSION, not LGTM)

  1. Verify it actually builds. The fix relies on the external package generating a type named exactly AvaloniaApp in the project's namespace. I can't confirm that from the MAUI repo. The strongest way to close this is for the integration test to build the --with-avalonia project, not just assert on generated file text — that would prove AvaloniaApp is generated and the project compiles. (gemini/opus-4.8 raised the same point about the new tests being content-only.)
  2. Per the package docs, embedding usually also wants a <UseAvaloniaEmbedding Include="…App" /> item and/or a concrete Avalonia App — please confirm the bootstrap generation alone produces everything UseAvaloniaEmbedding<AvaloniaApp>() needs at the mobile heads (vs. only the desktop head).

Minor (carried over)

  • The 11.0.0-preview.* floating version default pins consumers to whatever floats at restore time — consider a fixed version.

Net: the right fix mechanism is in place; the remaining ask is evidence it compiles (ideally a build assertion in SimpleTemplateTest). Happy to flip to LGTM once the Avalonia-on project is shown to build.

Multi-model review (gpt-5.5 · opus-4.8 · opus-4.6 · gemini-3.1-pro). Comments only — not a formal approval.

@drasticactions

drasticactions commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

With the pinning of versions, I'm fine with it. I'm not sure what's the right way for us to handling bumping the templates for new versions and what the other dependencies do. I'm open to discussions on that.

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

Labels

area-templates Project templates, Item Templates for Blazor and MAUI community ✨ Community Contribution

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants