Novedades de .NET MAUI para .NET 9
El enfoque de la interfaz de usuario de aplicaciones multiplataforma de .NET (.NET MAUI) en .NET 9 es mejorar la calidad del producto. Esto incluye la expansión de la cobertura de pruebas, las pruebas de escenario de un extremo a otro y la corrección de errores. Para obtener más información sobre las mejoras de calidad del producto en NET MAUI 9, consulta estas notas de la versión:
- .NET MAUI 9 RC2
- .NET MAUI 9 RC1
- Versión preliminar 7 de .NET MAUI 9
- Versión preliminar 6 de .NET MAUI 9
- .NET MAUI 9 Preview 5
- Versión preliminar 4 de .NET MAUI 9
- Versión preliminar 3 de .NET MAUI 9
- Versión preliminar 2 de .NET MAUI 9
- Versión preliminar 1 de .NET MAUI 9
Importante
Debido al trabajo con dependencias externas, como Xcode o Android SDK Tools, la directiva de compatibilidad de .NET MAUI difiere de la directiva de compatibilidad de .NET y .NET Core. Para obtener más información, consulta la directiva de soporte técnico de .NET MAUI .
Se requiere compatibilidad con Xcode 16, que incluye compatibilidad con SDK para iOS 18, iPadOS 18, tvOS 18 y macOS 15, al compilar con .NET MAUI 9. Xcode 16 requiere un equipo Mac que ejecute macOS 14.5 o posterior.
En .NET 9, .NET MAUI se distribuye como una carga de trabajo de .NET y varios paquetes NuGet. La ventaja de este enfoque es que permite anclar fácilmente los proyectos a versiones específicas, a la vez que te permite obtener una vista previa sencilla de compilaciones no publicadas o experimentales. Al crear un nuevo proyecto .NET MAUI, los paquetes NuGet necesarios se agregan automáticamente al proyecto.
Objetivos mínimos de implementación
.NET MAUI 9 requiere objetivos de implementación mínimos de iOS 12.2 y Mac Catalyst 15.0 (macOS 12.0). Los destinos mínimos de implementación de Android y Windows siguen siendo los mismos. Para más información, consulta Plataformas compatibles con aplicaciones .NET MAUI.
Controles nuevos
.NET MAUI 9 incluye dos nuevos controles.
Vista web híbrida
HybridWebView habilita el hospedaje de contenido HTML/JS/CSS arbitrario en una vista web y la comunicación entre el código de la vista web (JavaScript) y el código que hospeda la vista web (C#/.NET). Por ejemplo, si ya dispones de una aplicación de React JS, puedes hospedarla en una multiplataforma nativa de .NET MAUI y compilar el back-end de la aplicación mediante C# y .NET.
Para compilar una aplicación .NET MAUI con HybridWebView necesitas:
- Contenido web de la aplicación, que consta de HTML estático, JavaScript, CSS, imágenes y otros archivos.
- Un control HybridWebView como parte de la interfaz de usuario de la aplicación. Puedes hacerlo mediante una referencia a él en el XAML de la aplicación.
- Código en el contenido web y en C#/.NET, que usa las API de la HybridWebView para enviar mensajes entre los dos componentes.
Toda la aplicación, incluido el contenido web, se empaqueta y se ejecuta localmente en un dispositivo y se puede publicar en las tiendas de aplicaciones correspondientes. El contenido web se hospeda en un control de vista web nativo y se ejecuta dentro del contexto de la aplicación. Cualquier parte de la aplicación puede acceder a servicios web externos, pero no es un requisito.
Para más información, consulta HybridWebView.
Barra de título para Windows
El control TitleBar proporciona la capacidad de agregar una barra de título personalizada a la aplicación en Windows:
Puedes establecer una TitleBar como el valor de la propiedad de la Window.TitleBar en cualquier TitleBar:
<Window.TitleBar>
<TitleBar x:Name="TeamsTitleBar"
Title="Hello World"
Icon="appicon.png"
HeightRequest="46">
<TitleBar.Content>
<SearchBar Placeholder="Search"
PlaceholderColor="White"
MaximumWidthRequest="300"
HorizontalOptions="Fill"
VerticalOptions="Center" />
</TitleBar.Content>
</TitleBar>
</Window.TitleBar>
Un ejemplo de su uso en C# es:
Window window = new Window
{
TitleBar = new TitleBar
{
Icon = "titlebar_icon.png"
Title = "My App",
Subtitle = "Demo"
Content = new SearchBar { ... }
}
};
Una TitleBar es altamente personalizable a través de las propiedades del Content, el LeadingContent y el TrailingContent :
<TitleBar Title="My App"
BackgroundColor="#512BD4"
HeightRequest="48">
<TitleBar.Content>
<SearchBar Placeholder="Search"
MaximumWidthRequest="300"
HorizontalOptions="Fill"
VerticalOptions="Center" />
</TitleBar.Content>
<TitleBar.TrailingContent>
<ImageButton HeightRequest="36"
WidthRequest="36"
BorderWidth="0"
Background="Transparent">
<ImageButton.Source>
<FontImageSource Size="16"
Glyph=""
FontFamily="SegoeMDL2"/>
</ImageButton.Source>
</ImageButton>
</TitleBar.TrailingContent>
</TitleBar>
En la captura de pantalla siguiente se muestra el resultado de la apariencia:
Nota:
El control de la TitleBar
será compatible con Mac Catalyst en una versión futura.
Para obtener más información, vea TitleBar.
Mejoras de control
.NET MAUI 9 incluye mejoras de control.
Modo de enlace BackButtonBehavior OneWay
El modo de enlace para IsVisible
y IsEnabled
en un BackButtonBehavior en una aplicación de Shell ahora es BindingMode.OneWay
en lugar de BindingMode.OneTime
. De este modo, puedes controlar más fácilmente el comportamiento del botón Atrás en runtime, con enlaces de datos:
<ContentPage ...>
<Shell.BackButtonBehavior>
<BackButtonBehavior Command="{Binding BackCommand}"
IsVisible="{Binding IsBackButtonVisible}"
IconOverride="back.png" />
</Shell.BackButtonBehavior>
...
</ContentPage>
BlazorWebView
En iOS y Mac Catalyst 18, .NET MAUI 9 cambia el comportamiento predeterminado para hospedar contenido de un BlazorWebView a un localhost
. La dirección interna 0.0.0.1
se usa para hospedar el contenido que ya no funciona y, como resultado, BlazorWebView no carga ningún contenido y se representa como un rectángulo vacío.
Para participar en el uso de la 0.0.0.1
dirección, agrega el código siguiente al método CreateMauiApp
en MauiProgram.cs:
// Set this switch to use the LEGACY behavior of always using 0.0.0.1 to host BlazorWebView
AppContext.SetSwitch("BlazorWebView.AppHostAddressAlways0000", true);
Si encuentras bloqueos en Android con BlazorWebView, debes habilitar un modificador AppContext en el método CreateMauiApp
en tu clase MauiProgram
:
AppContext.SetSwitch("BlazorWebView.AndroidFireAndForgetAsync", true);
Este modificador permite a BlazorWebView activar y olvidar la eliminación asincrónica que se produce y, como resultado, corrige la mayoría de los interbloqueos de eliminación que se producen en Android. Para obtener más información, consulta Corrección de interbloqueos de eliminación en Android.
Botones en iOS
Button Los controles de iOS ahora respetan el espaciado, el relleno, el ancho del borde y los márgenes con mayor precisión que en las versiones anteriores. Ahora se cambiará el tamaño de una imagen Button grande al tamaño máximo, teniendo en cuenta el espaciado, el espaciado, el ancho del borde y los márgenes. Sin embargo, si contiene Button texto y una imagen, es posible que no sea posible ajustar todo el contenido dentro del botón, por lo que debe ajustar manualmente la imagen para lograr el diseño deseado.
CollectionView y CarouselView
.NET MAUI 9 incluye dos nuevos controladores opcionales en iOS y Mac Catalyst que aportan mejoras de rendimiento y estabilidad a CollectionView
y CarouselView
. Estos controladores se basan en las API de UICollectionView
.
Para utilizar estos controladores, agrega el código siguiente a la clase MauiProgram
:
#if IOS || MACCATALYST
builder.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler<Microsoft.Maui.Controls.CollectionView, Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2>();
handlers.AddHandler<Microsoft.Maui.Controls.CarouselView, Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2>();
});
#endif
ContentPage
En .NET MAUI 9, la propiedad HideSoftInputOnTapped también se admite en Mac Catalyst, así como Android e iOS.
Compatibilidad con la entrada de teclado flexible
.NET MAUI 9 agrega una nueva compatibilidad con la entrada de teclado flexible para Password
, Date
y Time
. Se pueden habilitar en los controles Editor y Entry:
<Entry Keyboard="Date" />
Text alignment
La enumeración TextAlignment agrega un miembro Justify
que se puede usar para alinear texto en controles de texto. Por ejemplo, puedes alinear horizontalmente el texto de Label con HorizontalTextAlignment.Justify
:
<Label Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. In facilisis nulla eu felis fringilla vulputate."
HorizontalTextAlignment="Justify"/>
TimePicker
TimePicker obtiene un evento TimeSelected, que se genera cuando cambia la hora seleccionada. El objeto TimeChangedEventArgs que acompaña al evento TimeSelected
tiene propiedades NewTime
y OldTime
, que especifican la hora nueva y antigua, respectivamente.
WebView
WebView agrega un evento de ProcessTerminated
que se genera cuando un proceso de WebView finaliza inesperadamente. El objeto WebViewProcessTerminatedEventArgs
que acompaña a este evento define propiedades específicas de la plataforma que indican por qué se produjo un error en el proceso.
Enlaces compilados en código
Los enlaces escritos en código suelen usar rutas de acceso de cadena que se resuelven en tiempo de ejecución con reflexión y la sobrecarga de hacerlo varía de una plataforma a otra plataforma. .NET MAUI 9 presenta un método de extensión SetBinding adicional que define enlaces mediante un argumento Func
en lugar de una ruta de acceso de cadena:
// in .NET 8
MyLabel.SetBinding(Label.TextProperty, "Text");
// in .NET 9
MyLabel.SetBinding(Label.TextProperty, static (Entry entry) => entry.Text);
Este enfoque de enlace compilado proporciona las ventajas siguientes:
- Mejora del rendimiento del enlace de datos mediante la resolución de expresiones de enlace en tiempo de compilación, en lugar de en tiempo de ejecución.
- Una mejor experiencia de solución de problemas para el desarrollador, ya que los enlaces no válidos se notifican como errores de compilación.
- IntelliSense durante la edición.
No todos los métodos se pueden usar para definir un enlace compilado. La expresión debe ser una expresión de acceso de propiedad simple. En los ejemplos siguientes se muestran expresiones de enlace válidas y no válidas:
// Valid: Property access
static (PersonViewModel vm) => vm.Name;
static (PersonViewModel vm) => vm.Address?.Street;
// Valid: Array and indexer access
static (PersonViewModel vm) => vm.PhoneNumbers[0];
static (PersonViewModel vm) => vm.Config["Font"];
// Valid: Casts
static (Label label) => (label.BindingContext as PersonViewModel).Name;
static (Label label) => ((PersonViewModel)label.BindingContext).Name;
// Invalid: Method calls
static (PersonViewModel vm) => vm.GetAddress();
static (PersonViewModel vm) => vm.Address?.ToString();
// Invalid: Complex expressions
static (PersonViewModel vm) => vm.Address?.Street + " " + vm.Address?.City;
static (PersonViewModel vm) => $"Name: {vm.Name}";
Además, .NET MAUI 9 agrega un método BindingBase.Create que establece el enlace directamente en el objeto con una Func
y devuelve la instancia del objeto de enlace:
// in .NET 8
myEntry.SetBinding(Entry.TextProperty, new MultiBinding
{
Bindings = new Collection<BindingBase>
{
new Binding(nameof(Entry.FontFamily), source: RelativeBindingSource.Self),
new Binding(nameof(Entry.FontSize), source: RelativeBindingSource.Self),
new Binding(nameof(Entry.FontAttributes), source: RelativeBindingSource.Self),
},
Converter = new StringConcatenationConverter()
});
// in .NET 9
myEntry.SetBinding(Entry.TextProperty, new MultiBinding
{
Bindings = new Collection<BindingBase>
{
Binding.Create(static (Entry entry) => entry.FontFamily, source: RelativeBindingSource.Self),
Binding.Create(static (Entry entry) => entry.FontSize, source: RelativeBindingSource.Self),
Binding.Create(static (Entry entry) => entry.FontAttributes, source: RelativeBindingSource.Self),
},
Converter = new StringConcatenationConverter()
});
Importante
Los enlaces compilados son necesarios en lugar de enlaces basados en cadenas en aplicaciones NativeAOT y en aplicaciones con recorte completo habilitado.
Enlaces compilados en XAML
En .NET MAUI 8, los enlaces compilados están deshabilitados para cualquier expresión de enlace XAML que defina la propiedad Source
y no se admita en varios enlaces. Estas restricciones se han quitado en .NET MAUI 9. Para obtener información sobre la compilación de expresiones de enlace XAML que definen la Source
propiedad, consulta Compilar enlaces que definen la Source
propiedad.
De forma predeterminada, .NET MAUI 9 genera advertencias de compilación para los enlaces que no usan enlaces compilados. Para obtener más información sobre las advertencias de enlaces compilados XAML, consulta Advertencias de enlaces compilados XAML.
Inserción de dependencia
En una aplicación de Shell, ya no es necesario registrar las páginas con el contenedor de inserción de dependencias a menos que quiera influir en la duración de la página en relación con el contenedor con los AddSingleton
métodos , AddTransient
o AddScoped
. Para obtener más información sobre estos métodos, consulte Duración de dependencias.
Desconexión del controlador
Al implementar un control personalizado mediante controladores, cada implementación del controlador de plataforma debe utilizar el método DisconnectHandler() para realizar cualquier limpieza de vista nativa, como anular la suscripción de eventos. Sin embargo, antes de .NET MAUI 9, .NET MAUI no invoca la implementación de DisconnectHandler() intencionadamente. En su lugar, tendrías que invocarlo tú mismo al elegir limpiar un control, como al navegar hacia atrás en una aplicación.
En .NET MAUI 9, los controladores se desconectan automáticamente de sus controles siempre que es posible, como al navegar hacia atrás en una aplicación. En algunas situaciones, es posible que no desees este comportamiento. Por lo tanto, .NET MAUI 9 agrega una propiedad adjunta de HandlerProperties.DisconnectPolicy
para controlar cuándo los controladores se desconectan de sus controles. Esta propiedad requiere un HandlerDisconnectPolicy argumento, con la enumeración que define los siguientes valores:
Automatic
, que indica que los controladores se desconectarán automáticamente. Se trata del valor predeterminado de la propiedad adjuntaHandlerProperties.DisconnectPolicy
.Manual
, que indica que los controladores tendrán que desconectarse manualmente invocando la implementación de DisconnectHandler().
En el ejemplo siguiente se muestra cómo establecer la propiedad adjunta de HandlerProperties.DisconnectPolicy
:
<controls:Video x:Name="video"
HandlerProperties.DisconnectPolicy="Manual"
Source="video.mp4"
AutoPlay="False" />
El código de C# equivalente es el siguiente:
Video video = new Video
{
Source = "video.mp4",
AutoPlay = false
};
HandlerProperties.SetDisconnectPolicy(video, HandlerDisconnectPolicy.Manual);
Además, hay un método de extensión de DisconnectHandlers que desconecta los controladores de un determinado IView:
video.DisconnectHandlers();
Al desconectarlo, el método de DisconnectHandlers propagará el árbol de control hasta que se complete o llegue a un control que haya establecido una directiva manual.
Compatibilidad con varias ventanas
.NET MAUI 9 agrega la capacidad de traer una ventana específica al frente en Mac Catalyst y Windows con el método Application.Current.ActivateWindow
:
Application.Current?.ActivateWindow(windowToActivate);
Implementación de AOT nativo
En .NET MAUI 9 puede participar en la implementación nativa de AOT en iOS y Mac Catalyst. La implementación de AOT nativa genera una aplicación MAUI de .NET que se ha compilado con antelación (AOT) en código nativo. Esto produce las siguientes ventajas:
- Tamaño reducido del paquete de la aplicación, normalmente hasta 2,5x más pequeños.
- Tiempo de inicio más rápido, normalmente hasta 2 veces más rápido.
- Tiempo de compilación más rápido.
Para obtener más información, consulte Implementación nativa de AOT en iOS y Mac Catalyst.
Incrustación nativa
.NET MAUI 9 incluye API completas para situaciones de inserción nativas, que anteriormente tenían que agregarse manualmente al proyecto:
var mauiApp = MauiProgram.CreateMauiApp();
#if ANDROID
var mauiContext = new MauiContext(mauiApp.Services, window);
#else
var mauiContext = new MauiContext(mauiApp.Services);
#endif
var mauiView = new MyMauiContent();
var nativeView = mauiView.ToPlatform(mauiContext);
Como alternativa, puedes usar el método ToPlatformEmbedded
, pasando en Window
para la plataforma en la que se ejecuta la aplicación:
var mauiApp = MauiProgram.CreateMauiApp();
var mauiView = new MyMauiContent();
var nativeView = mauiView.ToPlatformEmbedded(mauiApp, window);
En ambos ejemplos, nativeView
es una versión específica de la plataforma de mauiView
.
Para arrancar una aplicación nativa integrada en .NET MAUI 9, llama al método de extensión UseMauiEmbeddedApp
en el objeto MauiAppBuilder
:
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiEmbeddedApp<App>();
return builder.Build();
}
}
Para obtener más información, consulta Inserción nativa.
Plantillas de proyecto
.NET MAUI 9 agrega una plantilla de proyecto .NET MAUI Blazor Hybrid y aplicación web a Visual Studio, que crea una solución con una aplicación .NET MAUI Blazor Hybrid con una aplicación web Blazor, que comparte un código común en una biblioteca de clases Razor.
La plantilla también se puede usar desde dotnew new
:
dotnet new maui-blazor-web -n AllTheTargets
Diccionarios de recursos
En .NET MAUI 9, un XAML ResourceDictionary independiente (que no está respaldado por un archivo de código subyacente) tiene como valor predeterminado tener su XAML compilado. Para no participar en este comportamiento, especifica <?xaml-comp compile="false" ?>
después del encabezado XML.
Recorte
Ahora se admite el recorte completo estableciendo la $(TrimMode)
propiedad full
MSBuild en . Para obtener más información, consulte Recorte de una aplicación MAUI de .NET.
Incompatibilidades de recorte
Las siguientes características de .NET MAUI no son compatibles con el recorte completo y el recortador lo quitará:
- Expresiones de enlace en las que esa ruta de acceso de enlace se establece en una cadena. En su lugar, use enlaces compilados. Para obtener más información, consulta Enlaces compilados.
- Operadores de conversión implícitos, al asignar un valor de un tipo incompatible a una propiedad en XAML, o cuando dos propiedades de tipos diferentes usan un enlace de datos. En su lugar, debe definir un TypeConverter para el tipo y adjuntarlo al tipo mediante .TypeConverterAttribute Para obtener más información, vea Definir un TypeConverter para reemplazar un operador de conversión implícito.
- Carga de XAML en tiempo de ejecución con el método de LoadFromXaml extensión. Este XAML se puede hacer seguro al recortar anotando todos los tipos que se pueden cargar en tiempo de ejecución con el
DynamicallyAccessedMembers
atributo o elDynamicDependency
atributo . Sin embargo, esto es muy propenso a errores y no se recomienda. - Recepción de datos de navegación mediante .QueryPropertyAttribute En su lugar, debe implementar la IQueryAttributable interfaz en los tipos que necesitan aceptar parámetros de consulta. Para obtener más información, vea Procesamiento de datos de navegación mediante un único método.
- Propiedad
SearchHandler.DisplayMemberName
En su lugar, debes proporcionar un ItemTemplate para definir la apariencia de los resultados SearchHandler. Para obtener más información, vea Definir la apariencia del elemento de resultados de búsqueda.
Recorte de modificadores de características
.NET MAUI tiene directivas de optimizador, conocidas como modificadores de características, que permiten conservar el código de las características que no son seguras. Estas directivas de optimizador se pueden usar cuando la $(TrimMode)
propiedad build está establecida full
en , así como para NativeAOT:
Propiedad de MSBuild | Descripción |
---|---|
MauiEnableVisualAssemblyScanning |
Cuando se establece en true , .NET MAUI examinará los ensamblados para los tipos que implementan IVisual y para los atributos [assembly:Visual(...)] , y registrará estos tipos. De manera predeterminada, esta propiedad de compilación está establecida en false . |
MauiShellSearchResultsRendererDisplayMemberNameSupported |
Cuando se establece en false , se ignorará el valor de SearchHandler.DisplayMemberName . En su lugar, debes proporcionar un ItemTemplate para definir la apariencia de los resultados SearchHandler. De manera predeterminada, esta propiedad de compilación está establecida en true . |
MauiQueryPropertyAttributeSupport |
Cuando se establece en false , los atributos [QueryProperty(...)] no se usarán para establecer valores de propiedad al navegar. En su lugar, debes implementar la interfaz IQueryAttributable para aceptar parámetros de consulta. De manera predeterminada, esta propiedad de compilación está establecida en true . |
MauiImplicitCastOperatorsUsageViaReflectionSupport |
Cuando se establece en false , .NET MAUI no buscará operadores de conversión implícitos al convertir valores de un tipo a otro. Esto puede afectar a los enlaces entre propiedades con distintos tipos y establecer un valor de propiedad de un objeto enlazable con un valor de un tipo diferente. En su lugar, debes definir un TypeConverter para el tipo y adjuntarlo al tipo mediante el atributo TypeConverterAttribute. De manera predeterminada, esta propiedad de compilación está establecida en true . |
_MauiBindingInterceptorsSupport |
Cuando se establece en false , .NET MAUI no intercepta ninguna llamada a los métodos SetBinding y no intentará compilarlas. De manera predeterminada, esta propiedad de compilación está establecida en true . |
MauiEnableXamlCBindingWithSourceCompilation |
Cuando se establece en true , .NET MAUI compilará todos los enlaces, incluidos los donde se usa la Source propiedad . Si habilita esta característica, asegúrese de que todos los enlaces tengan el valor correcto x:DataType para que se compilen o borren el tipo de datos con x:Data={x:Null}} si el enlace no se debe compilar. De forma predeterminada, esta propiedad de compilación solo se establece en true cuando se habilita el recorte completo o la implementación de AOT nativa. |
Estas propiedades de MSBuild también tienen modificadores equivalentes AppContext :
- La
MauiEnableVisualAssemblyScanning
propiedad MSBuild tiene un modificador equivalente AppContext denominadoMicrosoft.Maui.RuntimeFeature.IsIVisualAssemblyScanningEnabled
. - La
MauiShellSearchResultsRendererDisplayMemberNameSupported
propiedad MSBuild tiene un modificador equivalente AppContext denominadoMicrosoft.Maui.RuntimeFeature.IsShellSearchResultsRendererDisplayMemberNameSupported
. - La
MauiQueryPropertyAttributeSupport
propiedad MSBuild tiene un modificador equivalente AppContext denominadoMicrosoft.Maui.RuntimeFeature.IsQueryPropertyAttributeSupported
. - La
MauiImplicitCastOperatorsUsageViaReflectionSupport
propiedad MSBuild tiene un modificador equivalente AppContext denominadoMicrosoft.Maui.RuntimeFeature.IsImplicitCastOperatorsUsageViaReflectionSupported
. - La
_MauiBindingInterceptorsSupport
propiedad MSBuild tiene un modificador equivalente AppContext denominadoMicrosoft.Maui.RuntimeFeature.AreBindingInterceptorsSupported
. - La
MauiEnableXamlCBindingWithSourceCompilation
propiedad MSBuild tiene un modificador equivalente AppContext denominadoMicrosoft.Maui.RuntimeFeature.MauiEnableXamlCBindingWithSourceCompilationEnabled
.
La manera más fácil de consumir un modificador de características es colocar la propiedad de MSBuild correspondiente en el archivo de proyecto de la aplicación (*.csproj), lo que hace que el código relacionado se recorte de los ensamblados MAUI de .NET.
Implementación de aplicaciones de Windows
Al depurar e implementar un nuevo proyecto MAUI de .NET en Windows, el comportamiento predeterminado en .NET MAUI 9 es implementar una aplicación desempaquetada. Para obtener más información, consulta Implementación y depuración de la aplicación .NET MAUI en Windows.
Compilador XAML
En .NET MAUI 9, los códigos de error del compilador XAML han cambiado su prefijo de XFC
a XC
. Asegúrese de actualizar las propiedades de compilación , $(WarningsNotAsErrors)
y $(NoWarn)
en los $(WarningsAsErrors)
archivos de proyecto de la aplicación, si se usa, para hacer referencia al nuevo prefijo.
Extensiones de marcado XAML
Todas las clases que implementan IMarkupExtension, IMarkupExtension<T>, IValueProvider y IExtendedTypeConverter deben anotarse con RequireServiceAttribute o AcceptEmptyServiceProviderAttribute. Esto es necesario debido a una optimización del compilador XAML introducida en .NET MAUI 9 que permite la generación de código más eficaz, lo que ayuda a reducir el tamaño de la aplicación y a mejorar el rendimiento del tiempo de ejecución.
Para obtener información sobre cómo anotar extensiones de marcado con estos atributos, consulta Proveedores de servicios.
Sincronización de Xcode
.NET MAUI 9 incluye la sincronización de Xcode (xcsync
), que es una herramienta que permite usar Xcode para administrar archivos específicos de Apple con proyectos de .NET, incluidos catálogos de recursos, archivos plist, guiones gráficos y archivos xib. La herramienta tiene dos comandos principales para generar un proyecto de Xcode temporal a partir de un proyecto de .NET y para sincronizar los cambios de los archivos Xcode de nuevo en el proyecto de .NET.
Usa dotnet build
con los comandos xcsync-generate
o xcsync-sync
para generar o sincronizar estos archivos y pase un archivo de proyecto y argumentos adicionales:
dotnet build /t:xcsync-generate
/p:xcSyncProjectFile=<PROJECT>
/p:xcSyncXcodeFolder=<TARGET_XCODE_DIRECTORY>
/p:xcSyncTargetFrameworkMoniker=<FRAMEWORK>
/p:xcSyncVerbosity=<LEVEL>
Para obtener más información, consulta sincronización de Xcode.
Interfaces API desusadas
.NET MAUI 9 deja obsoletas algunas API, que se eliminarán completamente en una versión futura.
Marco
El control Frame se marca como obsoleto en .NET MAUI 9 y se eliminará completamente en una versión futura. El control Border debe usarse en su lugar. Para más información, consulta Borde.
MainPage
En lugar de definir la primera página de la aplicación mediante la propiedad MainPage en un objeto Application, debes establecer la propiedad Page en una Window en la primera página de la aplicación. Esto es lo que sucede internamente en .NET MAUI cuando se establece la propiedad MainPage, por lo que no hay ningún cambio de comportamiento introducido por la propiedad MainPage que se marca como obsoleta.
En el siguiente ejemplo se muestra cómo establecer la propiedad Page en un objeto Window a través de la invalidación de CreateWindow
:
public partial class App : Application
{
public App()
{
InitializeComponent();
}
protected override Window CreateWindow(IActivationState? activationState)
{
return new Window(new AppShell());
}
}
El código que tiene acceso a la Application.Current.MainPage
propiedad ahora debe tener acceso a la Application.Current.Windows[0].Page
propiedad para las aplicaciones con una sola ventana. En el caso de las aplicaciones con varias ventanas, use la Application.Current.Windows
colección para identificar la ventana correcta y, a continuación, acceder a la Page
propiedad . Además, cada elemento cuenta con una Window
propiedad, a la que se puede acceder cuando el elemento forma parte de la ventana actual, desde la que se puede tener acceso a la Page
propiedad (Window.Page
). El código de plataforma puede recuperar el objeto de IWindow la aplicación con el método de Microsoft.Maui.Platform.GetWindow
extensión.
Aunque la MainPage propiedad se conserva en .NET MAUI 9, se quitará completamente en una versión futura.
Diseños de compatibilidad
Las clases de diseño de compatibilidad del espacio de nombres Microsoft.Maui.Controls.Compatibility han quedado obsoletas.
Llamadas de medida heredadas
Los siguientes VisualElement métodos de medida han quedado obsoletos:
Se trata de métodos de medida heredados que no funcionan correctamente con las expectativas de diseño de MAUI de .NET.
Como reemplazo, se ha introducido el VisualElement.Measure(Double, Double) método . Este método de devuelve el tamaño mínimo que un elemento necesita para mostrarse en el dispositivo. Los márgenes se excluyen de la medida, pero se indican con el tamaño. Este es el método preferido para medir una vista.
Además, la estructura SizeRequest está obsoleta. En su lugar, se debe usar Size.
.NET para Android
.NET para Android en .NET 9, que agrega compatibilidad con la API 35, incluye trabajo para reducir los tiempos de compilación y mejorar la capacidad de recorte de las aplicaciones para reducir el tamaño y mejorar el rendimiento. Para obtener más información sobre .NET para Android en .NET 9, consulte las notas de la versión siguientes:
- .NET para Android 9 RC2
- .NET para Android 9 RC1
- .NET para la versión preliminar 7 de Android 9
- Versión preliminar 6 de .NET para Android 9
- .NET for Android 9 Preview 5
- Versión preliminar 4 de .NET para Android 9
- Versión preliminar 3 de .NET para Android 9
- Versión preliminar 2 de .NET para Android 9
- Versión preliminar 1 de .NET para Android 9
Paquetes de recursos
.NET para Android en .NET 9 presenta la capacidad de colocar recursos en un paquete independiente, conocido como un paquete de recursos. Esto te permite cargar juegos y aplicaciones que normalmente serían mayores que el tamaño de paquete básico permitido por Google Play. Al colocar estos recursos en un paquete independiente, obtiene la capacidad de cargar un paquete que tiene un tamaño de hasta 2 Gb, en lugar del tamaño básico de paquete de 200 Mb.
Importante
Los paquetes de recursos solo pueden contener recursos. En el caso de .NET para Android, esto significa que los elementos que tienen la acción de compilación AndroidAsset
.
Las aplicaciones MAUI de .NET definen los recursos a través de la acción de compilación MauiAsset
. Un paquete de recursos se puede especificar mediante el atributo AssetPack
:
<MauiAsset
Include="Resources\Raw\**"
LogicalName="%(RecursiveDir)%(Filename)%(Extension)"
AssetPack="myassetpack" />
Nota:
Otras plataformas omitirán los metadatos adicionales.
Si tienes elementos específicos que deseas colocar en un paquete de recursos, puedes usar el atributo Update
para definir metadatos AssetPack
:
<MauiAsset Update="Resources\Raw\MyLargeAsset.txt" AssetPack="myassetpack" />
Los paquetes de recursos pueden tener diferentes opciones de entrega, que controlan cuándo se instalarán los recursos en el dispositivo:
- Los paquetes de tiempo de instalación se instalan al mismo tiempo que la aplicación. Este tipo de paquete puede tener un tamaño de hasta 1 Gb, pero solo puede tener uno de ellos. Este tipo de entrega se especifica con metadatos
InstallTime
. - Los paquetes de seguimiento rápido se instalarán en algún momento poco después de que la aplicación haya terminado de instalarse. La aplicación podrá iniciarse mientras se instala este tipo de paquete, por lo que debe comprobar que ha terminado de instalarse antes de intentar usar los recursos. Este tipo de paquete de activos puede tener un tamaño de hasta 512 Mb. Este tipo de entrega se especifica con metadatos
FastFollow
. - Los paquetes a petición nunca se descargarán en el dispositivo a menos que la aplicación lo solicite específicamente. El tamaño total de todos los paquetes de recursos no puede superar los 2 Gb y puede tener hasta 50 paquetes de activos independientes. Este tipo de entrega se especifica con metadatos
OnDemand
.
En las aplicaciones MAUI de .NET, el tipo de entrega se puede especificar con el atributo DeliveryType
en un MauiAsset
:
<MauiAsset Update="Resources\Raw\myvideo.mp4" AssetPack="myassetpack" DeliveryType="FastFollow" />
Para más información sobre los paquetes de recursos de Android, consulta Paquetes de recursos de Android.
Compatibilidad con Android 15
.NET para Android en .NET 9 agrega enlaces .NET para Android 15 (API 35). Para compilar para estas API, actualice la plataforma de destino del proyecto a net9.0-android
:
<TargetFramework>net9.0-android</TargetFramework>
Nota:
También puede especificar net9.0-android35
como marco de destino, pero el número 35 probablemente cambiará en futuras versiones de .NET para que coincidan con las versiones más recientes del sistema operativo Android.
Arquitecturas de 64 bits de forma predeterminada
.NET para Android en .NET 9 ya no compila los siguientes identificadores en tiempo de ejecución (RID) de forma predeterminada:
android-arm
android-x86
Esto debe mejorar los tiempos de compilación y reducir el tamaño de los archivos Android .apk
. Tenga en cuenta que Google Play admite la división de agrupaciones de aplicaciones por arquitectura.
Si necesita compilar para estas arquitecturas, puede agregarlas al archivo de proyecto (.csproj):
<RuntimeIdentifiers>android-arm;android-arm64;android-x86;android-x64</RuntimeIdentifiers>
O bien, en un proyecto de destino múltiple:
<RuntimeIdentifiers Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">android-arm;android-arm64;android-x86;android-x64</RuntimeIdentifiers>
Métodos de serialización de Android
Las mejoras en los métodos de serialización de Android en .NET 9 han hecho que la característica funcione de forma más confiable en las aplicaciones, pero aún no es el valor predeterminado. La habilitación de esta característica ha dado lugar a una mejora aproximada del 10 % en el rendimiento de una aplicación de prueba.
Los métodos de serialización de Android se pueden habilitar en el archivo de proyecto (.csproj) mediante la $(AndroidEnableMarshalMethods)
propiedad :
<PropertyGroup>
<AndroidEnableMarshalMethods>true</AndroidEnableMarshalMethods>
</PropertyGroup>
Para más información sobre la característica, consulte la documentación o la implementación de características en GitHub.
Mejoras de recorte
En .NET 9, los ensamblados de api de Android (Mono.Android.dll, Java.Interop.dll) ahora son totalmente compatibles. Para participar en el recorte completo, establezca la propiedad en el $(TrimMode)
archivo del proyecto (.csproj):
<PropertyGroup>
<TrimMode>Full</TrimMode>
</PropertyGroup>
Esto también habilita los analizadores de recorte, de modo que se introduzcan advertencias para cualquier código de C# problemático.
Para más información, consulte Recorte de granularidad.
.NET para iOS
.NET 9 en iOS, tvOS, Mac Catalyst y macOS usa Xcode 16.0 para las siguientes versiones de la plataforma:
- iOS: 18.0
- tvOS: 18.0
- Mac Catalyst: 18.0
- macOS: 15.0
Para más información sobre .NET 9 en iOS, tvOS, Mac Catalyst y macOS, consulta estas notas de la versión:
- .NET 9.0.1xx RC2
- .NET 9.0.1xx RC1
- Versión preliminar 7 de .NET 9.0.1xx
- Versión preliminar 6 de .NET 9.0.1xx
- .NET 9.0.1xx Preview 5
- Versión preliminar 4 de .NET 9.0.1xx
- .NET 9.0.1xx Preview 3
- .NET 9.0.1xx Preview 2
- .NET 9.0.1xx Preview 1
Enlaces
.NET para iOS 9 presenta la capacidad de usar versiones de varios destinos de .NET para enlaces iOS. Por ejemplo, un proyecto de biblioteca puede necesitar compilar para dos versiones distintas de iOS:
<TargetFrameworks>net9.0-ios17.0;net9.0-ios17.2</TargetFrameworks>
Esto generará dos bibliotecas, una con enlaces de iOS 17.0 y otra con enlaces de iOS 17.2.
Importante
Un proyecto de aplicación siempre debe tener como destino el SDK de iOS más reciente.
Mejoras de recorte
En .NET 9, los ensamblados de iOS y Mac Catalyst (Microsoft.iOS.dll, Microsoft.MacCatalyst.dll etc.) ahora son totalmente compatibles con el recorte. Para participar en el recorte completo, establezca la propiedad en el $(TrimMode)
archivo del proyecto (.csproj):
<PropertyGroup>
<TrimMode>Full</TrimMode>
</PropertyGroup>
Esto también habilita los analizadores de recorte, de modo que se introduzcan advertencias para cualquier código de C# problemático.
Para más información, consulte Recorte de granularidad.
AOT nativo para iOS y Mac Catalyst
En .NET para iOS 9, la compilación nativa de Ahead of Time (AOT) para iOS y Mac Catalyst aprovecha el recorte completo para reducir el tamaño del paquete y el rendimiento de inicio de la aplicación. NativeAOT se basa en el recorte completo, al participar en un nuevo entorno de ejecución.
Importante
La aplicación y sus dependencias deben ser totalmente recortables para poder usar esta característica.
NativeAOT requiere que las aplicaciones se compilan con advertencias de optimizador cero, con el fin de demostrar que la aplicación funcionará correctamente en tiempo de ejecución.