June 26th, 2025
1 reaction

Simpler XAML in .NET MAUI 10

David Ortinau
Principal Product Manager

Building UI in .NET MAUI with XAML continues to be the most popular approach. It’s easy to see the nesting structure of your UI, works for most use cases with hot reload, and it supports powerful state flow with data binding. One of the downsides is how verbose it can become. Every page requires you to declare the namespaces for any types used, provide prefixes for them, and of course use them. You’re likely a better developer than I am, but I very often use a different prefix for the same namespace in different files making quite a mess.

.NET 6 introduced global and implicit usings for C# which greatly reduced the using statements at the head of many C# files. Now in .NET 10 starting with Preview 5 we are introducing the same for XAML so you can declare your namespaces and prefixes in a single file and use them throughout. In fact, you can now omit the use of prefixes altogether!

Implicit Namespaces

This update begins by switching the global namespace that all XAML files used in .NET MAUI from xmlns="http://schemas.microsoft.com/dotnet/2021/maui" to xmlns="http://schemas.microsoft.com/dotnet/maui/global". Now there is a truly global namespace unique to your application where we can pack other namespaces for use throughout the codebase.

Opt-in to the implicit namespaces by adding this configuration to your project file.

<PropertyGroup>
    <DefineConstants>$(DefineConstants);MauiAllowImplicitXmlnsDeclaration</DefineConstants>
    <EnablePreviewFeatures>true</EnablePreviewFeatures>
</PropertyGroup>

Now your project will implicitly include these 2 namespaces which you’ve been accustomed to seeing in every XAML file since .NET MAUI first shipped.

xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

Because x: is used by the XAML inflator, you still need to use that prefix. With this change alone, your XAML for a view gets much tighter.

Before

<ContentPage 
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="MyApp.Pages.MyContentPage">
</ContentPage>

After

<ContentPage x:Class="MyApp.Pages.MyContentPage">
</ContentPage>

Global Namespaces

As you start to include classes of your own and from any of the many useful NuGet packages for .NET MAUI, the stack of xmlns in your XAML starts to grow like a layer cake. This is the MainPage from my app Telepathy

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:pageModels="clr-namespace:Telepathic.PageModels"
             xmlns:viewModels="clr-namespace:Telepathic.ViewModels"
             xmlns:models="clr-namespace:Telepathic.Models"
             xmlns:converters="clr-namespace:Telepathic.Converters"
             xmlns:controls="clr-namespace:Telepathic.Pages.Controls"
             xmlns:sf="clr-namespace:Syncfusion.Maui.Toolkit.TextInputLayout;assembly=Syncfusion.Maui.Toolkit"
             xmlns:cards="clr-namespace:Syncfusion.Maui.Toolkit.Cards;assembly=Syncfusion.Maui.Toolkit"
             xmlns:b="clr-namespace:Syncfusion.Maui.Toolkit.Buttons;assembly=Syncfusion.Maui.Toolkit"
             xmlns:pullToRefresh="clr-namespace:Syncfusion.Maui.Toolkit.PullToRefresh;assembly=Syncfusion.Maui.Toolkit"
             xmlns:bottomSheet="clr-namespace:Syncfusion.Maui.Toolkit.BottomSheet;assembly=Syncfusion.Maui.Toolkit"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             xmlns:aloha="clr-namespace:AlohaKit.Animations;assembly=AlohaKit.Animations"
             xmlns:effectsView="http://schemas.syncfusion.com/maui/toolkit"
             x:Class="Telepathic.Pages.MainPage"
             x:DataType="pageModels:MainPageModel"
             Title="{Binding Today}">
</ContentPage>

Yikes! Many of my XAML files use the same namespaces over and over such as pageModels, models, converters, controls, and so on. To globalize these, I created a GlobalXmlns.cs file where I can register these namespaces using XmlnsDefinition.

[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "Telepathic.PageModels")]
[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "Telepathic.Models")]
[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "Telepathic.Converters")]
[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "Telepathic.Pages.Controls")]
[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "Telepathic.ViewModels")]

I can also use the same to globalize third-party controls like the Syncfusion Toolkit for .NET MAUI, the Community Toolkit for .NET MAUI, and AlohaKit Animations used in this file.

[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "Syncfusion.Maui.Toolkit.TextInputLayout", AssemblyName = "Syncfusion.Maui.Toolkit")]
[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "Syncfusion.Maui.Toolkit.Cards", AssemblyName = "Syncfusion.Maui.Toolkit")]
[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "Syncfusion.Maui.Toolkit.Buttons", AssemblyName = "Syncfusion.Maui.Toolkit")]
[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "Syncfusion.Maui.Toolkit.PullToRefresh", AssemblyName = "Syncfusion.Maui.Toolkit")]
[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "Syncfusion.Maui.Toolkit.BottomSheet", AssemblyName = "Syncfusion.Maui.Toolkit")]
[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "http://schemas.syncfusion.com/maui/toolkit")]
[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "http://schemas.microsoft.com/dotnet/2022/maui/toolkit")]
[assembly: XmlnsDefinition(
    "http://schemas.microsoft.com/dotnet/maui/global",
    "AlohaKit.Animations", AssemblyName = "AlohaKit.Animations")]

After this I can remove all those declarations from the head of the file, resulting in a much cleaner read.

<ContentPage x:Class="Telepathic.Pages.MainPage"
             x:DataType="MainPageModel"
             Title="{Binding Today}">
</ContentPage>

Namespace Prefixes

Now that the xmlns are all gone, you may be wondering about the prefixes that had been defined in order to reference those controls in XAML. Well, you no longer need them! Notice in the previous example the x:DataType omits the pageModels: prefix previously required.

Let’s look at another example from this same page.

<BindableLayout.ItemTemplate>
    <DataTemplate x:DataType="models:ProjectTask">
        <controls:TaskView 
            TaskCompletedCommand="{Binding CompletedCommand, 
                                    Source={RelativeSource AncestorType={x:Type pageModels:MainPageModel}}, 
                                    x:DataType=pageModels:MainPageModel}"/>
    </DataTemplate>
</BindableLayout.ItemTemplate>

After

<BindableLayout.ItemTemplate>
    <DataTemplate x:DataType="ProjectTask">
        <TaskView 
            TaskCompletedCommand="{Binding CompletedCommand, 
                                    Source={RelativeSource AncestorType={x:Type MainPageModel}}, 
                                    x:DataType=MainPageModel}"/>
    </DataTemplate>
</BindableLayout.ItemTemplate>

Disambiguating Types

There will be times when you have types that collide and you’ll need to disambiguate them. I ran into this in another application where I have a custom control called FlyoutItem in my namespace ControlGallery.Views. In the XAML file it was being reference like <views:FlyoutItem /> and all was well. When I added ControlGallery.Views to the global namespace and removed the views: prefix, I encountered a collision because .NET MAUI already has a type FlyoutItem!

One way I could solve this would be to use the full path with namespace in the XAML like <ControlGallery.Views.FlyoutItem />. That is pretty long and not my preference.

Instead, there’s another attribute I can use alongside XmlnsDefinition and that’s XmlnsPrefix. Back in the GlobalXmlns.cs I can add a prefix for this namespace that’ll be usable globally in my application.

[assembly: XmlnsPrefix(
    "clr-namespace:ControlGallery.Views",
    "views")]

Now once again in XAML I can use that prefix like <views:FlyoutItem />.

Note

Before you go all in on this, be aware it’s a preview and there are issues to be ironed out. For example, the XAML Language Service needs some love to make it aware of what’s happening so you don’t get red squiggles everywhere. Additionally, work needs to be done to address the negative startup and runtime performance impact.

Resources

Known Issues

  • Debug builds are currently slower to startup
  • Runtime view inflation is slower
  • XAML editors incorrectly report unknown types via red squiggles (e.g. XLS0414)
  • Declaring prefixes for namespaces in the project requires including clr-namespace:

Feedback

You can get started by installing .NET 10 Preview 5 with the .NET MAUI workload or Visual Studio 17.14 Preview, and then creating a new project.

dotnet new maui -n LessXamlPlease

We need your feedback! Give this a go and let us know what you think by opening an issue on GitHub or sending me a note directly at david.ortinau@microsoft.com.

Author

David Ortinau
Principal Product Manager

David is a Principal Product Manager for .NET at Microsoft, focused on .NET MAUI. A .NET developer since 2002, and versed in a range of programming languages, David has developed web, environmental, and mobile experiences for a wide variety of industries. After several successes with tech startups and running his own software company, David joined Microsoft to follow his passion: crafting tools that help developers create better app experiences. When not at a computer or with his family, David ...

More about author

4 comments

  • David OrtinauMicrosoft employee Author

    Yes it’s been possible in MAUI before but you would have to pack into the maui namespace which we’ve changed.

    What trouble would you warn developers about should they opt into this?

  • David OrtinauMicrosoft employee Author

    As Thomas commented, packing namespaces has been possible for a while in WPF using ‘XmlnsDefinition’. The rest is additional work we’ve done to further the story in MAUI.

  • Thomas Levesque

    Using XmlnsDefinition to map namespaces to a default XML namespace is nothing new, it was already possible with WPF back in the day.
    I already thought it was a terrible idea back then: lumping everything into the same namespace is just asking for trouble. TBH I’m a little disappointed to see this practice recommended on an official Microsoft block…