.NET MAUI em 2026: Desenvolvimento Multiplataforma e Perguntas de Entrevista
Tutorial de .NET MAUI cobrindo desenvolvimento multiplataforma com .NET 10, handlers, MVVM, HybridWebView e perguntas de entrevista essenciais para 2026.

.NET MAUI (Multi-platform App UI) se consolidou como um framework multiplataforma de nível produção com o .NET 10. Lançado como uma versão Long-Term Support com suporte até novembro de 2028, o .NET MAUI 10 é distribuído como workload e pacotes NuGet, entregando melhorias em qualidade, desempenho e novas APIs como os aprimoramentos do HybridWebView e SafeAreaEdges. Este tutorial aborda a construção de um aplicativo multiplataforma, a arquitetura que faz o MAUI funcionar, e as perguntas de entrevista que os times de contratação fazem em 2026.
O .NET 10 é uma versão Long-Term Support (com suporte até novembro de 2028). O MAUI 10 prioriza qualidade e desempenho em vez de novos controles de UI, tornando-o a versão mais estável do MAUI até o momento. Agora é distribuído como workload do .NET e pacotes NuGet, permitindo o versionamento fixo por projeto.
Configurando um Projeto .NET MAUI 10 do Zero
O caminho mais rápido para um aplicativo MAUI funcional começa com a CLI do .NET. O .NET 10 introduz um template de projeto atualizado que inclui as configurações padrão do .NET Aspire, conectando telemetria e descoberta de serviços nativamente.
# Install the MAUI workload (if not already present)
dotnet workload install maui
# Create a new MAUI app
dotnet new maui -n CrossPlatformDemo
cd CrossPlatformDemo
# Run on Android emulator
dotnet build -t:Run -f net10.0-androidA estrutura de projeto único consolida o código específico de cada plataforma em uma pasta Platforms/ enquanto compartilha o restante. O arquivo MauiProgram.cs serve como raiz de composição, onde os serviços, fontes e handlers são registrados.
using Microsoft.Extensions.Logging;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
// Register services for dependency injection
builder.Services.AddSingleton<IApiService, ApiService>();
builder.Services.AddTransient<MainViewModel>();
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}A injeção de dependências no MAUI segue o mesmo padrão do ASP.NET Core. Serviços Singleton persistem durante toda a vida do aplicativo, serviços Transient são criados a cada solicitação, e serviços Scoped requerem cautela porque o MAUI não tem um conceito de escopo integrado como as requisições HTTP.
Handlers: A Arquitetura por Trás da Renderização Multiplataforma
O MAUI substituiu os renderers do Xamarin.Forms por uma arquitetura de handlers. Os handlers mapeiam cada controle multiplataforma para sua contraparte nativa através de uma camada de abstração fina. A diferença-chave: handlers são sem estado e desacoplados da view virtual, tornando-os mais rápidos e fáceis de personalizar.
using Microsoft.Maui.Handlers;
public class CustomEntryHandler : EntryHandler
{
protected override void ConnectHandler(MauiAppCompatEditText platformView)
{
base.ConnectHandler(platformView);
// Remove the default underline on Android
platformView.SetBackgroundColor(Android.Graphics.Color.Transparent);
}
}
// Register in MauiProgram.cs
builder.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler<Entry, CustomEntryHandler>();
});No .NET 10, os controles Entry e Editor no Android mudaram de AppCompatEditText para MauiAppCompatEditText, adicionando suporte nativo para o evento SelectionChanged. Os handlers aprimorados de CollectionView e CarouselView introduzidos no .NET 9 agora são os padrão no iOS e Mac Catalyst, resolvendo problemas de estabilidade que existiam há bastante tempo.
Android 16 Edge-to-Edge: Breaking Change e Correção Necessária
O Android 16 remove o mecanismo de opt-out do display edge-to-edge. Aplicativos que apontam para API 36 devem lidar corretamente com os insets das barras do sistema, ou o conteúdo será renderizado incorretamente. O .NET 10 introduziu uma breaking change silenciosa: no .NET 9, ContentPage respeitava as barras do sistema por padrão (comportamento Container), mas o .NET 10 muda o padrão para edge-to-edge (None).
Aplicativos migrando do .NET 9 para .NET 10 podem ver o conteúdo sendo renderizado sob a barra de status ou a barra de navegação no Android 15+. A correção requer definir explicitamente SafeAreaEdges para restaurar o comportamento anterior.
A correção envolve adicionar um estilo implícito global em App.xaml:
<!-- App.xaml -->
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CrossPlatformDemo.App">
<Application.Resources>
<ResourceDictionary>
<Style TargetType="ContentPage" ApplyToDerivedTypes="True">
<Setter Property="SafeAreaEdges" Value="Container" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>O enum SafeAreaEdges fornece controle granular:
None: conteúdo edge-to-edge sem padding de safe areaSoftInput: sempre adicionar padding para o tecladoContainer: fluir sob o teclado, ficar fora das barras e do entalheDefault: comportamento padrão da plataformaAll: respeitar todos os insets de safe area
Esta abordagem usa a Window Insets API em runtime, tornando-a compatível com Android 16 onde os opt-outs a nível de manifesto não funcionam mais.
MVVM com CommunityToolkit.Mvvm: Eliminando Código Repetitivo
O gerador de código-fonte CommunityToolkit.Mvvm elimina aproximadamente 80% da cerimônia MVVM. Sem implementação manual de INotifyPropertyChanged, sem wrappers de comando: os atributos controlam a geração de código.
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
public partial class MainViewModel : ObservableObject
{
private readonly IApiService _apiService;
public MainViewModel(IApiService apiService)
{
_apiService = apiService;
}
// Source generator creates the 'Title' property with change notification
[ObservableProperty]
private string _title = string.Empty;
// Source generator creates the 'IsLoading' property
[ObservableProperty]
private bool _isLoading;
// Source generator creates an async ICommand
[RelayCommand]
private async Task LoadDataAsync()
{
IsLoading = true;
try
{
Title = await _apiService.FetchTitleAsync();
}
finally
{
IsLoading = false;
}
}
}O XAML faz binding diretamente nas propriedades e comandos gerados:
<!-- MainPage.xaml -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:CrossPlatformDemo.ViewModels"
x:DataType="vm:MainViewModel">
<VerticalStackLayout Padding="20" Spacing="16">
<Label Text="{Binding Title}"
FontSize="24"
HorizontalOptions="Center" />
<Button Text="Load Data"
Command="{Binding LoadDataCommand}"
IsEnabled="{Binding IsLoading, Converter={StaticResource InverseBoolConverter}}" />
<ActivityIndicator IsRunning="{Binding IsLoading}"
IsVisible="{Binding IsLoading}" />
</VerticalStackLayout>
</ContentPage>O atributo x:DataType habilita compiled bindings, que são mais rápidos que bindings baseados em reflexão e produzem erros em tempo de compilação quando um caminho de binding está incorreto.
Pronto para mandar bem nas entrevistas de .NET?
Pratique com nossos simuladores interativos, flashcards e testes tecnicos.
Gerador de Código-Fonte XAML no .NET 10
O .NET MAUI 10 introduz um gerador de código-fonte XAML que compila o XAML em tempo de build em vez de parseá-lo em runtime. Isso melhora o desempenho de inicialização e detecta erros XAML durante a compilação.
Para habilitar a geração de código-fonte XAML, adicionar a propriedade ao arquivo de projeto:
<PropertyGroup>
<MauiXamlInflator>SourceGen</MauiXamlInflator>
</PropertyGroup>O .NET 10 Preview 5 também introduziu namespaces XML implícitos que eliminam as declarações xmlns repetitivas. Um arquivo GlobalXmlns.cs pode agregar múltiplos namespaces:
[assembly: XmlnsDefinition(
"http://schemas.microsoft.com/dotnet/maui/global",
"MyApp.Views")]
[assembly: XmlnsDefinition(
"http://schemas.microsoft.com/dotnet/maui/global",
"MyApp.Controls")]Com essa configuração, os arquivos XAML ficam mais limpos:
<!-- Antes -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:MyApp.Controls"
x:Class="MyApp.MainPage">
<controls:TagView />
</ContentPage>
<!-- Depois (com xmlns global) -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/maui/global"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.MainPage">
<TagView />
</ContentPage>HybridWebView no .NET 10: A Ponte entre Nativo e Web
HybridWebView permite incorporar conteúdo web dentro de um aplicativo MAUI mantendo comunicação bidirecional entre C# e JavaScript. O .NET 10 adiciona três capacidades: invocação JavaScript do tipo fire-and-forget, eventos de inicialização para configuração específica da plataforma, e interceptação de requisições web.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
// Initialization event for platform-specific tweaks
hybridWebView.WebViewInitialized += (sender, args) =>
{
System.Diagnostics.Debug.WriteLine("WebView ready");
};
}
// Call JavaScript from C#
private async void OnCallJsClicked(object sender, EventArgs e)
{
var result = await hybridWebView.InvokeJavaScriptAsync<string>(
"getFormData",
HybridSampleContext.Default.String
);
await DisplayAlertAsync("Result", result, "OK");
}
// Fire-and-forget: no return type needed (.NET 10)
private async void OnResetClicked(object sender, EventArgs e)
{
await hybridWebView.InvokeJavaScriptAsync("resetForm");
}
}Exceções JavaScript lançadas durante InvokeJavaScriptAsync agora são automaticamente encaminhadas para o .NET como exceções, eliminando falhas silenciosas. A interceptação de requisições web permite modificar headers ou fornecer respostas locais:
webView.WebResourceRequested += (s, e) =>
{
if (e.Uri.ToString().Contains("api/secure"))
{
e.Handled = true;
e.SetResponse(200, "OK", "application/json", GetCustomStream());
}
};APIs Obsoletas e Caminho de Migração
O .NET MAUI 10 marca como obsoletas várias APIs. Aplicativos que usam essas APIs devem migrar para as alternativas recomendadas.
ListView e células relacionadas: ListView, EntryCell, ImageCell, SwitchCell, TextCell e ViewCell estão obsoletos. Usar CollectionView em seu lugar, que tem melhor desempenho e estabilidade com os novos handlers do iOS/Mac Catalyst.
MessagingCenter: Tornado interno no .NET 10. Substituir por WeakReferenceMessenger do CommunityToolkit.Mvvm.
Métodos de animação: FadeTo, RotateTo, ScaleTo e métodos similares estão obsoletos. Usar os equivalentes async: FadeToAsync, RotateToAsync, ScaleToAsync.
TableView: Obsoleto em favor de CollectionView.
DisplayAlert/DisplayActionSheet: Substituídos por DisplayAlertAsync e DisplayActionSheetAsync.
Migração do Xamarin.Forms para o .NET MAUI
O Xamarin.Forms chegou ao fim do suporte em maio de 2024. A migração para o MAUI envolve mudanças estruturais além de uma simples troca de namespaces. A seguir, um checklist de migração baseado em conversões de projetos reais:
O Xamarin.Forms não tem mais suporte desde maio de 2024. Aplicativos que ainda rodam sobre Xamarin carregam riscos de segurança e compatibilidade. O .NET MAUI 10 (LTS, com suporte até novembro de 2028) é o alvo de migração designado.
- Estrutura do projeto: Converter os projetos específicos de cada plataforma para o modelo de projeto único do MAUI. Mover o código compartilhado para a raiz, código de plataforma sob
Platforms/. - Namespaces: Substituir
Xamarin.FormsporMicrosoft.Maui.ControlseXamarin.EssentialsporMicrosoft.Maui.Essentials(agora integrado ao MAUI). - Renderers para Handlers: Renderers personalizados precisam ser reescritos como handlers. A API de handlers é mais simples, mas a lógica de mapeamento difere.
- Inicialização: Substituir a inicialização em
App.xaml.csporMauiProgram.csusando o padrão builder. - Pacotes NuGet: Muitos pacotes da era Xamarin têm equivalentes no MAUI. Verificar a compatibilidade antes de atualizar.
- Injeção de dependências: O MAUI usa
Microsoft.Extensions.DependencyInjectionnativamente. Substituir qualquer container DI de terceiros ou chamadas aoDependencyService.
O .NET Upgrade Assistant automatiza partes dos passos 1-2, mas os handlers (passo 3) e ajustes de lógica de negócio requerem trabalho manual.
Perguntas de Entrevista .NET MAUI Essenciais para 2026
Estas perguntas refletem o que os times de contratação perguntam em 2026, com base no ecossistema atual do .NET 10. Para mais preparação de entrevistas C# e .NET, consultar o guia completo de entrevistas .NET.
Como a arquitetura de handlers do MAUI difere dos renderers do Xamarin.Forms?
Os renderers no Xamarin.Forms eram fortemente acoplados tanto ao controle multiplataforma quanto à view nativa, criando uma dependência bidirecional. Os handlers no MAUI são mapeadores sem estado: recebem notificações de mudança de propriedades e as aplicam à view nativa através de um dicionário de mappers. Esse desacoplamento significa que os handlers são mais fáceis de testar, estender e reutilizar. Os dicionários PropertyMapper e CommandMapper substituem o padrão de override OnElementPropertyChanged, tornando a personalização explícita em vez de estar enterrada em instruções switch.
Quais são as armadilhas dos tempos de vida de DI específicos do MAUI?
O MAUI suporta os tempos de vida Singleton, Transient e Scoped, mas o Scoped se comporta de maneira diferente do ASP.NET Core. Não existe um limite de escopo natural (como uma requisição HTTP). Um serviço Scoped registrado no MAUI age como um Singleton a menos que escopos personalizados sejam criados manualmente. Erros comuns: registrar um ViewModel como Singleton quando ele contém estado específico da página (dados obsoletos ao navegar), ou registrar uma conexão de banco de dados como Transient (esgotamento do pool de conexões). A regra geral: ViewModels são Transient, serviços são Singleton, e Scoped deve ser evitado a menos que o ciclo de vida do escopo seja gerenciado explicitamente.
Ao responder perguntas sobre injeção de dependências, é importante demonstrar compreensão de como o ciclo de vida do MAUI difere do modelo de escopo por requisição do ASP.NET Core. Os entrevistadores buscam consciência sobre vazamentos de memória e problemas de estado obsoleto específicos de aplicativos móveis de longa execução.
Qual a diferença entre compiled binding e binding baseado em reflexão no MAUI?
Bindings baseados em reflexão resolvem os caminhos de propriedades em tempo de execução usando System.Reflection, o que é lento e produz erros em runtime para erros de digitação. Compiled bindings, habilitados com x:DataType, resolvem os caminhos de binding em tempo de compilação. O compilador gera código de acesso direto às propriedades, pulando a reflexão completamente. Isso melhora o tempo de inicialização, reduz alocações de memória e detecta erros de binding durante o build. No .NET 10, o novo gerador de código-fonte XAML otimiza ainda mais ao compilar o XAML em tempo de build em vez de parseá-lo em runtime.
Quais estratégias existem para compartilhar código entre um aplicativo MAUI e um backend ASP.NET Core?
A abordagem recomendada utiliza uma biblioteca de classes compartilhada contendo DTOs, lógica de validação e regras de negócio. Tanto o aplicativo MAUI quanto o backend ASP.NET Core referenciam essa biblioteca. O .NET 10 reforça esse padrão com a nova integração .NET Aspire para MAUI, que fornece descoberta de serviços e telemetria entre projetos mobile e backend. Contratos compartilhados usando geradores de código-fonte do System.Text.Json garantem consistência na serialização. A restrição-chave: a biblioteca compartilhada deve ter como alvo net10.0 (não TFMs específicos de plataforma) para permanecer portável.
Qual a diferença entre HybridWebView e BlazorWebView no MAUI?
O BlazorWebView hospeda uma aplicação Blazor completa dentro do aplicativo MAUI. Componentes Razor são renderizados em uma WebView incorporada, mas o runtime .NET executa nativamente (não via WebAssembly). O HybridWebView é mais leve: carrega conteúdo HTML/CSS/JS estático e fornece interoperabilidade de C# para JavaScript sem a sobrecarga do framework Blazor. A escolha depende do caso de uso. O BlazorWebView é adequado para times com componentes Blazor existentes que desejam reuso de código. O HybridWebView é adequado para cenários onde conteúdo web existente (dashboards, mapas, editores) precisa de integração nativa sem um framework completo.
Para aprofundar esses conceitos, é possível praticar mais perguntas de entrevista .NET no SharpSkill com exercícios interativos.
Comece a praticar!
Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.
Sources
- What's new in .NET MAUI for .NET 10: documentação oficial cobrindo todas as funcionalidades do .NET 10 MAUI
- .NET MAUI GitHub Releases: notas de versão das releases de serviço 10.0.x
- Edge-to-Edge Is Now Mandatory in Android 16: guia de migração para os requisitos do Android 16
- MAUI GitHub Discussion #34171: feedback da comunidade sobre a estabilidade do .NET MAUI 10
O que Desenvolvedores .NET MAUI 10 Devem Lembrar
- O .NET MAUI 10 é uma versão LTS (suporte até novembro de 2028) focada em estabilidade e desempenho, tornando-o uma escolha confiável para aplicativos multiplataforma em produção
- O Android 16 torna o edge-to-edge obrigatório: adicionar
SafeAreaEdges="Container"como estilo global em App.xaml para restaurar o comportamento do .NET 9 - O gerador de código-fonte XAML (
MauiXamlInflator=SourceGen) compila o XAML em tempo de build, melhorando o desempenho de inicialização e detectando erros mais cedo - ListView, TableView e MessagingCenter estão obsoletos: migrar para CollectionView e WeakReferenceMessenger
- A arquitetura de handlers substitui os renderers do Xamarin por mapeadores sem estado, melhorando a testabilidade através de
PropertyMappereCommandMapper - Os geradores de código-fonte do CommunityToolkit.Mvvm removem a maior parte do código repetitivo MVVM: os atributos
[ObservableProperty]e[RelayCommand]substituem implementações manuais - O HybridWebView no .NET 10 adiciona chamadas JavaScript fire-and-forget, eventos de inicialização e interceptação de requisições para integração nativa-web
- A preparação para entrevistas deve focar na arquitetura de handlers vs renderers, armadilhas de tempos de vida de DI em aplicativos de longa execução, compiled bindings e as diferenças entre HybridWebView e BlazorWebView
Você saberia encontrar o bug em .NET?
Um trecho real, um bug escondido, uma tentativa por dia. Sem conta para testar.

Escrito por
Anthony Fillion-MailletFundador da SharpSkill
Desenvolvedor fullstack há mais de 10 anos. Dirige a SharpSkill e responde por tudo o que é publicado aqui.
Atualizado em 14 de setembro de 2026
Tags
Compartilhar
Artigos relacionados

.NET 10 em 2026: Novos Recursos, Native AOT e C# 14 para Preparação de Entrevistas
.NET 10 é a nova versão LTS com melhorias em Native AOT, extension members do C# 14, o keyword field e aplicações baseadas em arquivo. Guia completo de novos recursos, ganhos de performance e conhecimentos para entrevistas técnicas .NET em 2026.

Clean Architecture .NET em 2026: CQRS, MediatR e Perguntas de Entrevista para Desenvolvedores
Clean Architecture em .NET com CQRS e MediatR 14. Domine os padrões em camadas, pipeline behaviors e prepare-se para entrevistas de desenvolvedor senior.

Tempo de Vida do DbContext no ASP.NET Core: Performance vs Segurança de Threads em Operações Async
Domine o gerenciamento do tempo de vida do DbContext no ASP.NET Core. Aprenda quando usar scoped vs transient, como lidar com operações async de forma segura e otimizar performance com pooling de DbContext.