XAMLc in Xamarin.Forms: Optimize Static UI Without Breaking Dynamic XAML
XAML compilation moves Xamarin.Forms markup parsing into the build. Here is where it helps, how to verify it, and when runtime-loaded XAML makes the trade-off unsafe.
17 Jun 2026, 16:42 UTC

A Xamarin.Forms app with fixed pages can still pay to parse its XAML whenever those pages are loaded. The useful takeaway is narrow: XAML compilation, commonly called XAMLc, is a sensible build-time optimization for static XAML, but it is not a blanket switch for applications that load or inspect XAML at runtime.
There is also a lifecycle caveat. Microsoft’s Xamarin support ended on May 1, 2024. XAMLc is therefore a maintenance improvement for an existing Xamarin.Forms application, not a reason to begin new Xamarin work. For a new application, evaluate the current .NET application stack separately.
What XAMLc changes—and what it leaves alone
Without compilation, Xamarin.Forms loads a page’s XAML and parses it at runtime. With XAMLc, the build produces BAML, a binary representation of the XAML, and embeds it as a resource. The normal runtime parsing work is avoided for those compiled resources.
BAML is not a native UI. At runtime, Xamarin.Forms still creates the platform-specific controls, applies bindings, performs layout and executes application code. XAMLc can reduce markup-loading overhead, but it does not remove every startup cost or guarantee a visible improvement on every device.
The decision should follow the application’s XAML behavior. Fixed pages are good candidates. Runtime-loaded markup, reflection-based theme tooling and controls that inspect XAML objects require more caution.
Enable compilation in a classic Xamarin.Forms project
The following example assumes a classic Xamarin.Forms project using the MSBuild project format common in Xamarin.Forms 5.x-era applications. Project-level XAML compilation has existed since Xamarin.Forms 1.1, but confirm the syntax against the Xamarin.Forms build targets installed in your repository.
Open the application’s .csproj file and add this item to an existing PropertyGroup:
<PropertyGroup>
<XamlCompilation Include="resource" />
</PropertyGroup>This change requires write access to the project file and permission to build the application for its target platform. The resource value tells the Xamarin.Forms build targets to compile the handled XAML and include the resulting BAML as a resource.
Then perform these checks:
- Clean and rebuild. A successful build should report XAML compilation errors, if any, during the build rather than when the affected page is opened.
- Inspect the intermediate output. Look under the project’s
objdirectory for generated.bamlfiles. Their exact location varies by project system and build configuration. - Confirm the build targets exist. If no BAML is generated, check that the Xamarin.Forms package and its build targets are installed and that the project item was added to the intended project.
- Exercise the application. Open representative pages, navigate between them, rotate the device where supported, and run any theme or customization paths.
Do not treat the presence of a BAML file as proof that the application is faster. It confirms that compilation occurred; it does not measure the resulting startup improvement.
Use application behavior to decide whether to keep it
| Application behavior | Engineering decision | Verification |
|---|---|---|
| All pages are defined as build-time XAML | Enable XAMLc and measure it. | Build the Release configuration and test navigation and page initialization. |
The code loads XAML at runtime, often through an API named LoadFromXaml | Do not assume compiled resources cover dynamically supplied markup. | Search for runtime XAML loaders and test each path after enabling compilation. |
| A theme engine or third-party control inspects XAML objects at runtime | Treat this as a compatibility risk rather than a performance opportunity. | Test the affected control in a branch and compare its behavior with compilation disabled. |
| A XAML previewer or hot-reload view differs from the built application | Do not rely on the preview as the final authority. | Verify the compiled build on a device; previews may not represent the compiled resource path. |
| The build succeeds but no BAML appears | Correct the configuration before evaluating performance. | Check the project item, package references and installed build targets. |
Because the example enables compilation at project level, a problematic page can affect more than one screen. A small compatibility test is more useful than assuming that successful compilation also proves runtime compatibility.
Measure startup on the device that matters
Compare two Release builds: one with the XAML compilation item and one without it. Use the same physical device, the same application state and the same measurement method. Cold-start the application repeatedly, disable the debugger, and record the time from process launch to the first meaningful rendered frame using the platform’s available startup or frame profiler.
Compare a median of several runs rather than a single launch. Avoid mixing Debug and Release measurements, because the build configuration introduces unrelated differences. If the improvement is negligible, the change may not justify its compatibility cost. If a dynamic-XAML path fails, remove the XamlCompilation item and rebuild to return that project to runtime parsing.
The practical sequence is therefore: inventory runtime XAML loading, enable compilation in a controlled branch, verify the generated BAML, test the affected UI paths, and compare cold-start behavior on representative hardware. Keep the change only when the build is clean, behavior is preserved and the measured benefit justifies continuing to maintain Xamarin.Forms code.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.