Archivo de la etiqueta: xamarin

Solución si en Visual Studio 2022 para Windows no te muestra el dispositivo físico en un proyecto para iOS de Xamarin.Forms

Pues eso… que empecé un proyecto de Xamarin Forms en Visual Studio 2022 con los proyectos para Android y Windows (UWP) pero no añadí el de iOS y después me planteé añadirlo porque, aunque yo no lo uso (no me funcionan en mi iPhone 7 Plus) mi hijo David sí le funcionan en su iPhone y en el iPad (David es de los que gustan usar las cosas de Apple, de hecho, está certificado como técnico en todo lo referente a Apple), y me encontré que ahora no me mostraba el «dispositivo» local en la lista de dispositivos, solo los habituales para usar con un Mac en línea.

Ver las capturas 1 y 2 para que así entiendas mejor a lo que me refiero.
En la captura 1 están las opciones que suelen mostrarse si todo está bien, y en la captura 2 se echa en falta el dispositivo físico.

Captura 1. El dispositivo físico aparece en la lista.

Captura 2. El dispositivo físico no aparece en la lista.

Nota:
Además de lo que te cuento aquí, para que se muestren los dispositivos físicos debes tener instalado en tu Windows el iTunes de Apple.

Aparte de lo comentado en la nota anterior, otra cosa que debes tener en tu proyecto para iOS es que haya una referencia a Xamarin.Forms (se me olvidó añadirla y casi me vuelvo loco buscando cómo solucionarlo) y ya, de esas cosas que te dan pro probar… probé a verificar las dependencias del proyecto y eché en falta la referencia a Xamarin.Forms, y fue añadirla y… ¡voilà! ahí está el dispositivo disponible, otra cosa es que funcione la aplicación, pero al menos está 😉

En las capturas 3 y 4 puedes ver las referencias del proyecto para iOS.
En la captura 3 no estaba incluido Xamarin.Forms y por eso no se mostraba el dispositivo físico.
En la captura 4 ya está esa referencia y ahora sí que muestra en la lista de dispositivos (si está conectado al USB del equipo, todo hay que aclararlo) el iPhone 7 plus que es el que yo heredé de mi hijo David 😉

Captura 3. Aquí falta la referencia a Xamarin.Forms (y no se muestra el dispositivo físico)

Captura 4. Con la referencia a Xamarin.Forms sí muestra los dispositivos físicos.

Y esto es todo… ya sabes… espero que te sea de utilidad (y espero que a mí me vuelva a serlo cuando me pase de nuevo… jejejeje, que conociéndome, seguro que me vuelve a pasar).

Nos vemos.
Guillermo

Solución al error en .NET MAUI: Error MSB4018 The «XamlCTask» task failed unexpectedly.

Pues eso… todo el rollo que te conté ayer… al final tenía una fácil solución o su solución era fácil. Y es no usar el idioma de Cervantes.

Ya te conté todo el rollo con las aplicaciones usando las plantillas de .NET MAUI con Visual Studio 2022, que al final no compilaban por el dichoso error: Error MSB4018 The «XamlCTask» task failed unexpectedly. Y no era por otra cosa que por usar caracteres acentuados (con tilde) en el diseñador de XAML.

En la otra aplicación que me funcionaba, seguramente «de casualidad» no tenía ese tipo de caracteres, y me estaba volviendo loco. Porque ya no sabía qué hacer.

Y hoy, leyendo otro «feedback» al querer postear el error, era porque alguien quería usar un «dibujito» en el XAML y resulta que le daba error… y la solución era usar el código que corresponde a ese dibujo para así mostrarlo.

Yo lo he solucionado poniendo en el código el texto a mostrar.

Y lo que quería hacer era un ejemplo en el que se escribe un número en una caja de texto, se pulsa en un botón y se muestra el número escrito. Este ejemplo tan «simplón» es solo para demostrar a esta gente de Visual Studio / .NET MAUI que el control Entry falla y que solo admite el texto que se asigne, ya sea en tiempo de diseño o en tiempo de ejecución, pero que si escribes algo, ese valor no se tiene en cuenta, solo se usa el inicialmente asignado.

En la captura 1 puedes ver el proyecto en ejecución en el proyecto para Windows (UWP), y ahí te muestro que a pesar de haber escrito otro número distinto al asignado inicialmente (5) en la etiqueta no muestra el que se haya escrito.

Captura 1. La aplicación para .NET MAUI en funcionamiento.

Pues ya lo sabes (y espero yo saberlo también) 😉

Nos vemos.
Guillermo

Solucionando problemas con los proyectos de .NET MAUI en Visual Studio 2022 (o casi)

Pues eso… seguimos con los «problemitas» de Visual Studio 2022 y .NET MAUI. Después del fallo que te comenté anoche, me puso en la labor de crear un nuevo proyecto de .NET MAUI en Visual Studio 2022, con idea de comentar otro de los fallos con los que me encontré y es que en los controles Entry no se cambia el valor que hayas asignado (en diseño o por código).

Creé un nuevo proyecto de .NET MAUI, pero… nada de nada… el error que me mostraba (después de varios «cleanings» y «rebuilds» era que: XamlCTask «nosequénosecuántos» y ahí se quedaba.

Esto ya me pasó otra vez, lo solucioné (pero no recordaba como lo hice), por eso estoy escribiendo esto… por si lo soluciono lo tendré a mano 😉

Lo que ahora estoy haciendo (o el Windows 11 está haciendo) es esto:

Paso 1: Ejecutar maui-check.

En la línea de comandos (yo he abierto el terminal de Windows 11) escribe:
maui-check.

Esto comprueba si el «.NET MAUI» está correctamente instalado.

Nota:
Si esa utilidad no la tienes instalada… pues… tendrás que instalarlo, tal como te dije hace unos meses.

dotnet tool install -g redth.net.maui.check

Paso 2: Descargar e instalar todo lo que necesita .NET MAUI.

Escribe en la línea de comandos o la terminal de Windows 11:
dotnet workload install maui

Esto descargará e instalará lo que necesite tu equipo.

Ver la captura 1 con los dos comandos comentados.

Captura 1. El terminal de Windows 11 con los dos comandos.
Captura 1. El terminal de Windows 11 con los dos comandos.

Aunque esto no soluciona el error ese de Error MSB4018 The «XamlCTask» task failed unexpectedly. 🙁

Paso 3: Crear un nuevo proyecto.

Yo lo he creado desde la línea de comandos:
dotnet new maui -n MauiApp3
MauiApp3 es el nombre del proyecto que le he dado.

Pero también lo puedes crear desde el propio Visual Studio 2022.

En nuevo proyecto escribe MAUI en la búsqueda y pulsa INTRO y te mostrará los proyectos de .NET MAUI. Selecciona el primero tal como te muestro en la captura 2.

Captura 2. Nuevo proyecto de .NET MAUI.
Captura 2. Nuevo proyecto de .NET MAUI.

Paso 4: Editar el proyecto en Visual Studio 2022 e indicar que admita aplicaciones de Windows.

Lo abro con Visual Studio 2022, (o lo creo, tal como te he indicado en el paso anterior), edito el fichero del proyecto (en el explorador de soluciones pulsa con el botón secundario en el proyecto y selecciona Edit Project File) y quito el comentario en la línea:

<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows')) and '$(MSBuildRuntimeType)' == 'Full'">$(TargetFrameworks);net6.0-windows10.0.19041</TargetFrameworks>

En el valor TargetFrameworks que está justo encima de esa línea con los «frameworks» incluidos en el proyecto: net6.0-ios;net6.0-android;net6.0-maccatalyst.

Si ahora ejecutas el proyecto te dará error, ya que el «framework» que usará será el primero de la lista: net6.0-ios. Aunque arriba esté indicado que será en Windows Machine.

Para solucionarlo, debes cambiar el target framework indicado en la aplicación de Windows y seleccionar el de Windows (ver la captura 3):

Captura 3. Indicar el framework para las aplicaciones de Windows.
Captura 3. Indicar el framework para las aplicaciones de Windows.

Abajo, en la lista de errores más o menos te da pistas.

Y si después de eso (y tienes suerte) al pulsar F5 debería mostrarte la aplicación de ejemplo (ver la captura 4).

Captura 4, la aplicación de ejemplo en funcionamiento.
Captura 4, la aplicación de ejemplo en funcionamiento.

Nota interna pal Guille:
El proyecto que funciona (sin añadir código propio) es: MauiApp2 y MauiApp3 que están en «C / source / repos».

Una cosa a tener en cuenta:

Si pruebas con Android (emulador o dispositivo), y supongo que para iOS también, el framework se asignará correctamente, pero si vuelves a querer usar la aplicación en Windows, tendrás que volver a indicar el net6.0-windows10.0.19041.

Ahora no se te ocurra añadir tu propio código… jajaja porque es cuando empieza el espectáculo del error ese que te dije antes en el paso 2: Error MSB4018 The «XamlCTask» task failed unexpectedly.

A ver si consigo solucionarlo, porque ni haciendo todo lo anterior me ha funcionado.

Porque funcionar (aunque regulín-regulán) me ha funcionado, pero ya no recuerdo qué hice. A ver si doy con lo que fue… y te voy contando, porque ya son cerca de las 4 de la tarde del nuevo horario y hay hambre 😉

*** Seguimos

A ver… creo que era lo que comentaban en este «reporte de error»: VS 2022 MAUI project templates missing.

Ejecutando este código: dotnet new -i Microsoft.Maui.Templates indica que está todo instalado (otra cosa es que añadas una nueva página al proyecto, en ese caso, como es Xamarin.Forms te dará errores por todos lados, pero básicamente es cambiar las definiciones de los «usings» y cambiar los xmlns del diseñador).

En mi caso, al ejecutar ese código (ver la captura 5) dice que está todo instalado (y que ya lo estaba).

Captura 5. Instalar los templates de .NET MAUI.
Captura 5. Instalar los templates de .NET MAUI.

*** Seguimos (2)…

Yo qué sé… tengo un proyecto que funciona (mal, pero funciona con mi propio código), pero no consigo que los nuevos proyectos tengan el código que yo quiera (que de eso se trata, ¿no?).

Bueno, ahora sí, si lo soluciono, y sé/recuerdo cómo lo he solucionado, lo pondré aquí o en un post nuevo…

Solo me queda añadir una nueva página y ahí escribir el nuevo código…

Actualizado el 1 de noviembre de 2021.

Pues resulta que he conseguido crear un nuevo proyecto desde el propio Visual Studio 2022, añadirle código propio y hacer que funcione, y de paso comprobar que eso de los controles Entry falla.

Pero solo he tenido 3 oportunidades, desde la cuarta, ya no funciona… vuelve a salir el error de: The «XamlCTask» task failed unexpectedly.

Y ya… pues casi que lo dejo, hasta ver si es casualidad o es que se puede hacer algo para solucionar ese «dichoso» error.

Lo mandaré a esta gente a ver qué dicen… seguro que a ellos nunca les pasa 😉

¡¡¡Resulta que todo el problema eran las «tildes»!!!

Pues eso… he quitado una tilde que tenía en «número» y ahora funciona bien… jajajaja, como se suele decir: ¡pa mearse y no echar gota!

Es decir, el error de The «XamlCTask» task failed unexpectedly es porque hay caracteres «no normales».

Nos vemos.
Guillermo

.NET MAUI aún está muy verde (comparado con Xamarin.Forms)

Pues eso… por fin he logrado hacer algo medianamente útil con .NET MAUI y Visual Studio 2022 (acceso a datos, para ser más concreto) y… pues que en la aplicación de Windows (UWP) funciona bien, pero en la de Android ni de coña… Y ya con la de iOS ni te digo… es que ni siquiera compila… en fin…

La de Android se inicia, pero cuando digo de acceder a una base de datos, da error.

Seguramente será por el «idioma» (codificación). Ya que en las aplicaciones de Xamarin.Forms para que pueda acceder a las bases de datos de SQL Server le tengo que decir (a iOS también) que use la codificación WEST y entonces si funciona (ver la captura 1), pero no tengo ni repajolera idea de cómo hacerlo en .NET MAUI. 🙁

Captura 1. La opción en Xamarin.Forms para indicar que use la codificación oeste (west)
Captura 1. La opción en Xamarin.Forms para indicar que use la codificación oeste (west)

De todas formas, aunque funcione en Windows (me vale para las pruebas), hay cosas tan simples como que un Entry (el típico TextBox de .NET Framework, o casi) no permita que se cambie el contenido… Bueno, permitir, lo permite, pero como si le echaras un vaso de agua al mar para que aumente de nivel… Es decir, que no vale pa ná

En fin… y el día 8 de noviembre quieren lanzar el Visual Studio 2022… ¡que lo lancen! pero bien lejos… porque falla más que una escopetilla de plomos…

Eso sí, uno le dice a esta gente que fallos va encontrando, pero… ¡a ellos no les falla!… jajajaja me rio yo solo… por no llorar…

De hecho, con un bug «tonto» de seleccionar código con las teclas ALT+SHIFT (suelo hacerlo bastante cuando quiero copiar el código para colorearlo y publicarlo en este blog, por ejemplo).

Pues no hay forma de que esta gente sigan los mismos pasos que ya les he indicado varias veces, ellos lo hacen a su manera, y de esa forma no falla… pero no es lo mismo. Ya que, si yo quiero seleccionar algo que está indentado, en Visual Studio 2022 falla, sin embargo, en Visual Studio 2019 va bien.

Si tienes curiosidad, puede ver el «feedback» que yo lo titulé (en inglés para que no se pierdan mucho): BUG: Selecting block of text with SHIFT+ALT (+ Down, Left keys) moves the selection start down (not always).

Y algunos más… que, hasta pueden resultar graciosos, como el que al seleccionar el texto de esta forma se quedan varios cursores y si escribes algo se pone ese texto en todos los cursores que haya (uno por cada línea seleccionada).

Este es el enlace (y el título): BUG VS2022: Selecting with ALT+SHIFT, releasing the selection, the blue and red cursor remains and if you type the text typed is set in several places.

Bueno… no te canso más… aunque, si vives por estos lares… esta noche podrás dormir una hora más… que nos cambian el horario de verano al de invierno y… a las 3 de la madrugada serán las 2… 😉

Buenas noches.

Nos vemos.
Guillermo

Windows 11 maneja mejor la memoria en las app para Windows UWP de Xamarin.Forms

Pues eso… en la app para mobile en la que estoy inmerso desde hace meses, desarrollada con Visual Studio 2019 y Xamarin.Forms para Android, iOS y Windows UWP; uno de los problemillas que me he encontrado con la versión para Windows UWP (Universal Windows Platform) es que cuando le da el punto empieza a consumir memoria como ella sola… llegando hasta casi un GIGA y ni que la minimices ni nada, no para de subir, y normalmente también se ralentiza.

Sin embargo, en las pruebas que he hecho en el Windows 11, en una máquina virtual, ya que los de Windows Insiders dicen que mis equipos (un portátil con 3 años y una torre de hace un mes) no cumplen las características requeridas, y eso que la máquina virtual usa los recursos (procesador, memoria) desde el «computador» donde se está ejecutando esa máquina virtual. Pero ese es otro tema. Lo que te decía, en las pruebas hechas en el Windows 11 el consumo es muchísimo menor, además de que al minimizar la aplicación libera esa memoria, según indica el administrador de tareas (Task Manager) del propio Windows.
En las figuras 1 y 2 puedes ver las capturas de esos dos casos.

 

Figura 1. La app abierta en Windows 11 (159,8 MB)

 

Figura 2. La app minimizada baja a 7,0 MB el consumo de la memoria y con el simbolico ese verde 😉

La versión de Windows 11 que tengo instalada es Windows 11 Pro versión 21H2 build 22000.168 co_release. Esta creo que se instaló usando el «canal» Dev Channel (que instala lo último que tengan), aunque momentáneamente lo cambié al Beta Channel por aquello de que mandaron un email recomendando que se utilizara ese canal y en la ventana de Windows Insider Program la marcan como recomendada.

Aparte de esto, el Windows 11 me está gustando… antes me parecía que los cambios eran prácticamente estéticos (el look), pero ahora veo que hay algo más 😉

Y ya no te entretengo más… que hoy es sábado, sabadate… camisa nueva y p*****e (o eso dicen).

 

Nos vemos.
Guillermo

P.S.
He actualizado las fotos, para que se vena mejor y ocupen menos espacio, que no es plan de utilizar más datos de la cuenta 😉

Cómo refrescar los datos en aplicaciones de Xamarin.Forms o .NET MAUI

Pues eso… con el título de este post: Cómo refrescar los datos en aplicaciones de Xamarin.Forms o .NET MAUI, aparte de referirme que es para apliciones multiplataforma/multidispositivos creadas con Xamarin.Forms o .NET MAUI, me refiero a esos casos en los que quiero que se muestre un mensaje (por ejemplo en el texto de una etiqueta) mientras la aplicación hace cosas que pueden tardar un poco, como leer los datos de una base de datos o contar hasta cientocuincuentamilmillonesdetrillones, por decirte algo 😉

En .NET Framework / aplicaciones de Windows.Forms, yo suelo usar el fatídico (para algunos) Application.DoEvents(), que sí, que dicen que usando el Thread.Sleep se supone que hace lo mismo, pero yo te digo que no, a mí no me ha funcionado nunca.

Con la aplicación mobile en la que estoy enfrascado desde hace ya unos 3 meses, intenté el Sleep, intenté crear/usar un temporizador (otra de las formas en que hago con .NET Framework esa pequeña pausa para refrescar), pero nada de nada… Probé haciendo los métodos asíncronos para que fuesen «agüeitable» (async y await), pero nada de nada…

Sin embargo ayer, buscando en la red de redes (Inernet por si no sabías que así se le llama algunas veces), me encontré con una consulta en la que respondían eso que tanto estaba buscando saber cómo hacer, y la respuesta la encontré, (casi como de costumbre), en stackoverflow, concretamente aquí.

Y es usando Task.Delay(...) a la que tenemos que indicar los milisegundos de espera.
En esa respuesta indican dos formas de hacerlo: de forma asíncrona y de forma síncrona, decirte que la que a mí me ha funcionado es la asíncrona, la otra, como si miraras al cielo esperando ver pasar un elefante rosa… por decir algo… Vamos, que ni de coña esperaba…

Y como he visto que funcionaba, me he creado un método compartido en la clase App para que me sea fácil usarla desde cualquier parte de la aplicación, a ese método lo he llamdo Refrescar y recibe un parámetro con los milisegundos que quieres esperar antes de seguir, yo suelo usar el valor 300, que es el que casi siempre uso en los temporizadores que pongo en las aplicaciones de escritorio creadas con .NET Framework.
Este es el código de ese método (en C# ya que por ahora las aplicaciones de Xamarin.Forms / .NET MAUI son (y segurián siendo solo) para el cochambros lenguaje ese de los puntos y comas.

Y si te ha molestado que diga cochambroso lenguaje, de verdad que lo siento, pero… es lo que me parece a mí, al menos en la forma que yo lo uso, es una pequeña caca comparado con Visual Basic. Ya sabes: cochambros es lleno de mugre o cochambre que viene de cocho, puerco… ¡UF! me vas a odiar como seas fanático del C#, pero es lo que hay, es mi opinión, pero con fundamentos.

El código

Bueno, a lo que vamos, este es el código:

/// <summary>
/// Hacer una pequeña pausa para refrescar.
/// </summary>
/// <param name="intervalo">El tiempo que hay que esperar (en milisegundos).</param>
async public static Task Refrescar(int intervalo = 300)
{
    await Task.Delay(intervalo);
}

El valor predeterminado es de 300 milisegundos, es decir, menos de un tercio de segundo, incluso con 100 iría bien, pero…

Cómo lo utilizo

En uno de los casos, tengo una etiqueta en la que muestro el total de datos que leo de la base de datos, mientras se hace la búsqueda muestro un mensaje diciendo algo como: Leyendo los datos…, hago la pausa, (se refreca el contenido de la etiqueta) y mientras llamo al método que lee los datos, en el que actualizo esa etiqueta con los datos mostrados, etc.

LabelInfoReservas.Text = $"Leyendo las reservas de '{ElCliente.Nombre}'...";

// refrescar...
//await Task.Delay(300);
await App.Refrescar();

await asignarLasReservas();

En la siguiente captura, puedes verlo (me ha dado tiempo a hacerla a pesar de que había pocos datos que leer porque, esa es la impresión que a mí me da, las aplicaciones para Windows-UWP de Xamari.Forms / .NET MAUI son algo lentas… en ocasiones muuuucho más lentas que las aplicaciones para escritorio hechas con .NET Framework 4.8. Tanto que esta app móvil no podremos usarla al 100% en la playa porque hay poca cobertura móvil (de datos) que ya se hace insufrible utilizarla, y en este caso no creo que sea porque está hecha con C# 😉

Captura de la app con el mensaje mientras lee los datos de la base de datos.

Y ya está… eso es todo, simple, ¿verdad? pues… sí… 😉

Nos vemos.
Guillermo

Acceder a los recursos definidos en ResourceDictionary o Application.Resources desde código (C#) (Xamarin.Forms y NET MAUI)

Pues eso… es alqo que me ha estado dando un poco la lata en las aplicaciones de Xamarin.Forms, y es acceder a los recursos definidos en el fichero App.xaml tanto dentro de Application.Resources como en las definiciones de ResourceDictionary.

Aquí te explico cómo hacerlo en los dos casos, además de usar un fichero externo con las definiciones de los recursos.

 

Contenido:

 

Empezaré con las definiciones directas en los recursos de App.xaml.

Acceder desde código a las definiciones de recursos definidos en App.xaml

 —

Acceder desde código a las definiciones de Application.Resources

Para acceder a los recursos definidos en Application.Resources desde código es simple (al menos cuando se sabe cómo 😉 ).
Por ejemplo, si tenemos dos recursos definidos, uno ColorAzul1 y el otro ColorAzul2, de esta forma:

<Application.Resources>
    <Color x:Key="ColorAzul">#0073cf</Color>
    <Color x:Key="ColorRojo">Firebrick</Color>
</Application.Resources>

Si queremos usar uno u otro desde código dependiendo de alguna condición, por ejemplo que estemos usando la app en Android o en iOS y que ocurra alguna otra condición (ver nota), podemos hacerlo de esta forma:

if (esUnaPrueba)
    LabelInternet.TextColor = (Color)Application.Current.Resources["ColorAzul"];
else
    LabelInternet.TextColor = (Color)Application.Current.Resources["ColorRojo"];

Como ves en el código a los recursos definidos en Application.Resources se accede usando Application.Current.Resources["key del recurso"];

El cast usando en el código de ejemplo es necesario ya que el valor devuelto por ese elemento de la colección Resources es de tipo object.
Esa forma de hacerlo la conocí gracias a esta entrada en los foros de Xamarin.

Nota: Lo de que ocurra alguna otra condición es porque en los recursos podemos indicar para qué plataforma lo definimos. Aunque para el caso de los colores no sé muy bien como se haría, para el resto puedes ver esto.

 

Acceder desde código a las definiciones de ResourceDictionary

Por otro lado, si el recurso lo tenemos en una rama de ResourceDictionary, por ejemplo de esta forma:

    <ResourceDictionary>
        <Color x:Key="Color2Azul">#0073cf</Color>
        <Color x:Key="Color2Rojo">Firebrick</Color>
    </ResourceDictionary>
</Application.Resources>

Para acceder a esos recursos definidos en ResourceDictionary desde el código de C# lo tendrás que hacer de esta otro forma:

if (esAzul)
    LabelInternet2.SetDynamicResource(Label.TextColorProperty, "Color2Azul");
else
    LabelInternet2.SetDynamicResource(Label.TextColorProperty, "Color2Rojo");

El truco para usar esa otro forma, lo saqueé del mismo post que te indiqué antes, pero estaba abajo del todo, concretamente de aquí.
A lo mejor hay otra forma, pero… a mí me ha servido esta que te muestro.

 

Ahora toca explicarte cómo agregar ficheros de recursos (ResourceDictionary) y usarlos directamente en los recursos del fichero App.Xaml.

Definir recursos (ResourceDictionary) en fichero separado y usarlo en App.xaml

También puedes usar esos ficheros de recursos desde una página concreta.

Ahora también te lo explicaré, que a mí me da mucho coraje cuando se comenta algo así en un post y después no se explica porque se supone que se sabe cómo hacerlo… y aunque puede que sepas cómo hacerlo (eso hasta yo lo sabía hace unos cuantos años cuando empecé con todo esto de XAML, hará al menos 16 años), puede que hayas encontrado este post al buscar cómo hacer eso concretamente y no el resto de cosas que estoy explicando.

Crear un fichero XAML de recursos del tipo ResourceDictionary

En el proyecto añade un nuevo fichero del tipo XAML, yo no he visto cómo agregar uno directamente desde la ventana de agregar nuevo elemento al proyecto, así que, puedes agregar un fichero de texto y después cambiarle la extensión de .txt a .xaml 😉
En la figura 1 puedes ver más claro cómo agregar ese fichero.

Figura 1. Añadir un nuevo fichero al proyecto.

Nota: Después de agregar el fichero y cambiar la extensión (ya sea a la hora de crearlo como es el ejemplo de la figura 1 o si le cambias posteriormente la extensión, es recomendable cerrarlo y después abrirlo, si no, el Intellisense no se cosca de que es del tipo que tiene la extensión. Esto también es válido para ficheros de código al que inicialmente lo has creado como .TXT y después lo cambias a .CS.

Ese fichero estará vacío, así que… habrá que ponerle algo de código, concretamente este que te muestro para que sea un fichero válido del tipo ResourceDictionary.

<?xml version="1.0" encoding="utf-8"?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

</ResourceDictionary>

Aquí voy a definir algunas cosas para ver cómo funciona, tanto en modo diseño (en el código XAML de las páginas) como desde el código (en estos ejemplos solo de C# que es lo que me permite usar loss proyectos de Xamarin.Forms.
Aunque lo mismo hago pruebas con aplicaciones del tipo UWP que ahí sí se pueden crear proyetos de C# o de mi querido Visual Basic 😉

En ese fichero de recursos agrega las siguientes definiciones de colores y estilos de etiquetas para que quede como te muestro a continuación.

<?xml version="1.0" encoding="utf-8"?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

    <Color x:Key="Color3Azul">#0073cf</Color>
    <Color x:Key="Color3Rojo">Firebrick</Color>
    <Color x:Key="Color3Blanco">White</Color>

    <Style x:Key="LabelEjemplo3" TargetType="{x:Type Label}">
        <Setter Property="FontSize" Value="Small"/>
        <Setter Property="FontAttributes" Value="None" />
        <Setter Property="HorizontalTextAlignment" Value="Start"/>
        <Setter Property="HorizontalOptions" Value="FillAndExpand"/>
        <Setter Property="Padding" Value="4"/>
        <Setter Property="TextColor" Value="Green"/>
        <Setter Property="BackgroundColor" Value="{DynamicResource Key=Color3Blanco}"/>
    </Style>
    <Style x:Key="LabelEjemplo3Azul" TargetType="{x:Type Label}">
        <Setter Property="FontSize" Value="Small"/>
        <Setter Property="FontAttributes" Value="Italic" />
        <Setter Property="HorizontalTextAlignment" Value="Start"/>
        <Setter Property="HorizontalOptions" Value="FillAndExpand"/>
        <Setter Property="Padding" Value="4"/>
        <Setter Property="TextColor" Value="{StaticResource Color3Azul}"/>
        <Setter Property="BackgroundColor" Value="{StaticResource Color3Blanco}"/>
    </Style>
    <Style x:Key="LabelEjemplo3Rojo" TargetType="{x:Type Label}">
        <Setter Property="FontSize" Value="Small"/>
        <Setter Property="FontAttributes" Value="Bold" />
        <Setter Property="HorizontalTextAlignment" Value="Start"/>
        <Setter Property="HorizontalOptions" Value="FillAndExpand"/>
        <Setter Property="Padding" Value="4"/>
        <Setter Property="TextColor" Value="{StaticResource Color3Rojo}"/>
        <Setter Property="BackgroundColor" Value="{StaticResource Color3Blanco}"/>
    </Style>

</ResourceDictionary>

 

Usar un fichero de recursos (ResourceDictionary) desde una página

Y con eso puedes hacer lo siguiente para incluir el fichero de recursos en una página concreta.
Se supone que la página está en una carpeta (en mi caso en la carpeta elGuille) y el fichero de recursos está en el raíz del proyecto. Por tanto tengo que usar ../ para acceder al fichero que está en un path superior. Esto es como cuando accedes a los ficheros, así que no creo que tengas problemas para entenderlo… o eso espero, porque en esto sí que no voy a profundizar 😉

<ContentPage.Resources>
    <ResourceDictionary Source="../ResourceDictionaryElGuille.xaml"/>
</ContentPage.Resources>

Nota: Si estuviera en otra carpeta, tendrás que indicarlo en el path de la propiedad Source. Por ejemplo si la carpeta está en el raíz del proyecto y se llama Recursos, el valor de Source quedaría así: Source="/Recursos/ResourceDictionary2.xaml".

 

Usar por código un recurso (estilo) definido en ResourceDictionary.

Para usar, en este ejemplo, un estilo definido, habría que hacerlo de esta forma:

if (usarEstiloAzul)
    LabelInternet3.SetDynamicResource(Label.StyleProperty, "LabelEjemplo3Azul");
else
    LabelInternet3.SetDynamicResource(Label.StyleProperty, "LabelEjemplo3Rojo");

Es decir, como en el caso de los colores, pero en lugar de usar TextColorProperty, es decir, una propiedad, uso StyleProperty para indicar que es un estilo lo que quiero aplicar desde el fichero de recursos.

 

Por último voy a explicarte cómo agregar ese fichero de recursos (ResourceDictionary) al fichero App.xaml y así poder usarlo en toda la aplicación.

Usar un fichero de recursos (ResourceDictionary) en App.xaml

Seguramente esto parece no tener mucho sentido, ya que si defines los recursos directamente en el fichero App.xaml ¿por qué hacerlo en otro fichero?

En mi caso, la respuesta es la siguiente:
Yo tengo un proyecto de Xamarin Forms que define las clases a usar en la aplicación móvil (Android, iOS y UWP), llamaré Proyecto1 a ese proyecto base (el que se usa desde los proyectos específicos de cada plataforma).

Ahora creo otro proyecto móvil (que llamaré Proyecto2) que tiene también como punto de entrada el fichero App (es lo habitual) y que usa la DLL del proyecto anterior (Proyecto1). Lo hago así, porque la funcionalidad es la misma, pero por circunstacias que no viene al caso profundizar mucho en ellas, tuve que crear otro proyecto móvil (el que usa lo definido en Proyecto2), pero para no repetir todo el código que ya tengo hecho, añadí una referencia a Proyecto1 en el Proyecto2.

Y lo curioso es que aunque las clases definidas en Proyecto1 se supone que utiliza los recursos que haya en el App.xaml del Proyecto1, al ejecutar la aplicación (que usa Proyecto2) me da error de que no encuentra los recursos, por tanto, tuve que copiar todas las definiciones del fichero App.xaml del Proyecto1 en el App.xaml del Proyecto2.

Hasta aquí todo bien, sin problemas. ¿No?

Pero ahora decido añadir un nuevo estilo o cambiar alguno de los que hay… ¿Qué tengo que hacer? Pues muy fácil: MODIFICAR ambos ficheros App.xaml con esos estilos modificados.

Y la verdad es que para un despistao como yo, eso es unproblema, ya que me puedo tirar un buen rato comprobando porqué no funciona con los nuevos estilos definidos… Hasta caer en la cuenta de que no están definidos en los dos ficheros.
Sí, así de torpe es elGuille 😉

¿Solución? Crear un fichero en el que estén todos los recursos y ese fichero usarlo en los dos proyectos. Y eso es lo que he hecho y como he visto que en la rede de redes no está explicado cómo hacer esto, seguramente porque es algo trivial o fácil, pero la cuestión es que para mí no era tan trivial ni fácil, y como no encontraba la solución… me puse a probar con lo que ya había encontrado y… ahora ya lo tengo claro y para que tú también lo tengas claro, si es que necesitas hacerlo, aquí te lo explico.

En realidad la solución es fácil, lo que me traía de cabeza es que usando esas definiciones con esto: Application.Current.Resources["estilo"], no me funciona (y eso aún no lo he solucionado), así que, tuve que usar lo que te he comentado antes de aplicar los estilos que están en una declaración ResourceDictionary (Acceder desde código a las definiciones de ResourceDictionary), es decir, usando esto: Control.SetDynamicResource(TipoControl.StyleProperty, "estilo"), ya que al fin y al cabo, esos recursos definidos en otro fichero en realidad están definidos como ResourceDictionary.

Vamos con los ejemplos de código, empezando por el código XAML a usar en App.xaml:

<Application.Resources>
    <ResourceDictionary Source="ResourceDictionaryElGuille.xaml"/>

Es decir, se hace de la misma forma que para añadirlo a una página normal.
En este caso no indico ningún path en Source porque ese fichero de recursos está en el mimo directorio que App.xaml.

Si ves el código fuente en GitHub (es el mismo proyecto que los ejemplos de los Trucos para Xamarin.Forms y .NET MAUI en dispositivos) comprobarás que en App.xaml he dejado ese código anterior (el de usar un ResourceDictionary definido en otro fichero) además de otras definiciones que también están en bloques ResourceDictionary.

 

A tener en cuenta

Lo que sí debes tener en cuenta es que si todo lo defines en bloques de ResourceDictionary no podrás acceder a esas definiciones por código usando Application.Current.Resources[«key»].

Es decir, el código usado en el primer ejemplo fallará si esos dos recursos (ColorAzul y ColorRojo) no están directamente definidos en los recursos de la aplicación.

Pero puedes tenerlos definidos en dos sitios diferentes sin conflictos.

Para que todos estos ejemplos funcionen he definido esos dos valores tanto en Application.Resources como en el ResourceDictionary del fichero ese externo.

Por tanto, el código XAML de App.xaml empezaría de esta forma: (sigue con otras definiciones de ResourceDictionary, una que estaba ya en ese fichero cuando se creé el proyecto y los que he definido para usar los colores Color2Azul y Color2Rojo del segundo ejemplo que te mostré antes).
También he definido los recursos ColorAzul y ColorRojo para que el primer ejemplo no de error. Y sí, esas mismas claves están definidas en ambos ficheros, y sin conflictos. 😉

<Application.Resources>
    <ResourceDictionary Source="ResourceDictionaryElGuille.xaml"/>

    <ResourceDictionary>
        <Color x:Key="Color2Azul">#0073cf</Color>
        <Color x:Key="Color2Rojo">Firebrick</Color>
    </ResourceDictionary>

Como ya te he explicado antes, la forma de usar esos valores definidos en un ResourceDictionary es usando el código del segundo ejemplo de este post.

 

Y esto es todo… espero que te haya sido de utilidad.

El código fuente de estos ejemplos (y los del 2 de junio) están en GitHub: ElGuille-Ejemplos.

 

Nos vemos.
Guillermo

Instalando los proyectos de VS2019 v16.11 Preview 1 para .NET MAUI Preview 4

Pues eso… que he instalado el Visual Studio 2019 versión 16.11 Preview 1 para poder usar los proyectos de .NET MAUI Preview 4 y como no había tipos de proyectos para .NET MAUI, y lo que se indica en esa página para tenerlos no es completo, he tenido que buscar en la WEB cómo hacerlo y aquí te pongo unas capturas de ese proceso de configuración de .NET MAUI para poder tener los tipos de proyectos en Visual Studio 2019 v11 Preview 1.

Lo primero es decirte que al PowerShell deberían cambiarle las combinaciones de colores, porque lo que es un servidor, no me resulta fácil ver algunos de los avisos y comandos/opciones… así que… si tampoco puedes verlos en las capturas… imagina lo que pone… 😀

De todas formas te resumo los pasos:

Tienes que abrir una ventana de comandos o PowerShell y escribir:
dotnet tool install -g redth.net.maui.check
A continuación (esto es lo que no vi en la página del anuncio de .NET MAUI Preview 4, aunque ahora releyéndola si lo he visto) escribir:
maui-check
Aunque antes de esto deberías escibir estos dos comandos:
primero:
dotnet new nugetconfig
y después:
dotnet nuget add source -n maui-preview https://aka.ms/maui-preview/index.json
O al menos así lo hice yo, aunque creo que primero escribí el primero el de dotnet tool install
En cualquier caso, si ya lo has hecho, no habrá problemas, tal como verás en las siguientes capturas, ya que te dirá que ya está hecho 😉

Figura 1. No me muestran los proyectos de .NET MAUI.
Figura 2. Ahí dice que ya lo he instalado… pero yo no veo ese texto… tuve que copiarlo para verlo…
Figura 3. Crear la configuración de NuGet y añadirla… aunque ya lo hice según ahí me indica
Figura 4. La comprobación de si está instalado lo necesario para usar .NET MAUI (tuve que «fix» todo eso…).
Figura 5. Y paciencia mientras instala los SDKs, emuladores, etc.
Figura 6. Paciencia mientras sigue instalando…
Figura 7. Hasta que termine de comprobar e instalar.
Figura 8. Ahora si hay proyectos para .NET MAUI en Visual Studio 2019 v11 Preview 1

Por supuesto, estos pasos no habrá que hacerlos una vez que tanto el .NET MAUI como el Visual Studio 2019 (o 2022) que lo soporte estén más actualizados. O eso espero, si no… pues eso… ¡será un rollo!

Y si quieres saber qué se irá incluyendo en las próximas preview de .NET MAUI, aquí tienes el roadmap mostrado cuando sacaron la preview 4.

No he tenido oportunidad de probarlo, he creado un proyecto nuevo, pero la máquina virtual que tengo parece que falla mucho o es que el Visual Studio 2019 versión 16.11 Preview 1 hace que falle, no lo sé… no tengo la paciencia para averiguarlo, entre otras cosas porque esa máquina virtual (en Hyper-V) va lenta y me ralentiza mi equipo, al menos con las cosas que tengo abiertas y que por ahora son más urgentes que probar el .NET MAUI, pero lo probaré… y cuando lo haga, lo sabrás… si sigues lo que publico aquí en el blog o en mi feis, así que… te invito a que entres en la página de elGuille ne el feis: elGuille.info en Facebook.

Espero que te sea de utilidad… ya sabes que esa es siempre la intención. 😉

Nos vemos.
Guillermo

Soluciones a los ejercicios de Trucos para Xamarin.Forms y .NET MAUI en dispositivos

Pues eso… aquí tienes los ejercicios y las soluciones propuestos en el post Trucos para Xamarin.Forms y .NET MAUI en dispositivos. También los tienes disponibles en GitHub.

Los ejercicios eran:

Si quieres, como ejercicio de práctica, puedes hacer lo siguiente:

Ejercicio 1:

Añade un panel (StackLayout) con la orientación horizontal, de esa forma los controles que metas dentro de ese stack se mostrarán uno al lado del otro, pon un Switch seguido de un botón con el texto «Un Switch» y después otro Switch y otro botón con el texto «Otro Switch» (o lo que te de la gana pero que no sea demasiado largo).
En este caso el texto no pillará todo el ancho y verás que no se ve igual en iOS / iPhone que en Android o UWP/Windows.
Si no puedes probarlos en distintos dispositivos emuladores, te pondré la respuesta con algunas capturas de los tres sistemas que utilizo con Xamarin.Forms.

Nota:
Probando el ejercicio, compruebo que el poner más espacios al final, no tienen el efecto deseado, así que… si es iOS usa el valor 6,0 para la propiedad Padding.

Otra cosa interesante que puedes hacer (ejercicio 2) es que las etiquetas estén alineadas en el centro vertical, es decir, para que no se vean con el texto tan arriba, sino en el centro de la propia etiqueta.

Estas son las soluciones

Al ejercicio 1 y 2:

<StackLayout Orientation="Horizontal" Padding="4" Spacing="3">
    <Label Text="2 Switch con botones: " VerticalOptions="Center"/>
    <Switch />
    <!-- Los espacios detrás no se respetan... habrá que usar padding -->
    <Button Text=" Un Switch "
            Padding="{OnPlatform iOS='6,0', Android='6,0', Default=4}"/>
    <Switch />
    <Button Text=" Otro Switch "
            Padding="{OnPlatform iOS='6,0', Android='6,0', Default=4}"/>
</StackLayout>

Nota:
El valor ColorAzul2 está definido en App.xaml.

En ej ejercicio 2 lo que debes usar es: VerticalOptions="Center"

Capturas de los ejemplos

Aquí te dejo algunas capturas (me gusta que los posts tengan imágenes 😉 )

Ya sabes, pulsa en la imagen para verla en grande.

Figura 1. Página principal del proyecto en Android.

Figura 2. La solución a los ejercicios en Android.

Figura 3. Página principal del proyecto en iPhone.

Figura 4. Las soluciones en iPhone, pero en modo oscuro no se ve la etiqueta…

Figura 5. Solución a los ejercicios en iPhone (usando el tema claro).

Y esto es todo.

Lee el post de estos ejercicios porque hay cambios.

Nos vemos.
Guillermo

Trucos para Xamarin.Forms y .NET MAUI en dispositivos

Pues eso… te voy a relacionar varios trucos sobre cómo usar el código (y el código de marcado XAML) para dispositivos móviles (Android, iOS y UWP -Windows 10-) usando Xamarin.Forms (Mono mobile) y seguramente servirá para .NET MAUI, la que será el sustituto de Xamarin cuando .NET 6.0 esté en fase release (sobre noviembre de este año 2021).

Nota:
El código mostrado a la hora de escribir este post (2 de junio de 2021 a las 11:15) es para Xamarin.Forms y C#.
Cuando tenga ejemplos de .NET MAUI lo indicaré si es diferente al de Xamarin.

Los trucos

El código con los ejemplos, ejercicios y soluciones están publicados en GitHub.

  1. Saber la plataforma (Android, iOS o UWP) y el tipo de dispositivo (Phone, Tablet, TV, Watch, Desktop)
  2. Poner varios valores en el código XAML usando OnPlatform, OnIdiom, etc.
    1. Ejercicio 1
    2. Ejercicio 2
  3. Si al crear un proyecto no te aparecen los emuladores ni dispositivos
  4. Acceder a los recursos definidos en ResourceDictionary o Application.Resources desde código (C#) (en otro post del 14-jun-2021)

Saber la plataforma (Android, iOS o UWP) y el tipo de dispositivo (Phone, Tablet, TV, Watch, Desktop)

Algunas veces es conveniente saber si la aplicación está funcionando en un dispositivo Android, iOS o compatible con UWP (Windows 10 escritorio o móvil, Xbox, etc.), tanbién si es un móvil, escritorio, tablet, etc.

La primera (la plataforma) se averigua con Platform y OnPlatform y los valores aceptados son los indicados en la tabla 1 (de la ayuda de Xamarin.Forms) que corresponden al tipo DevicePlatform:

La segunda (el tipo de dispositivo) se averigua con Idiom y OnIdiom y los valores de DeviceIdiom que son los que te muestro en la tabla 2.

Cuando usamos Platform o Idiom lo haremos por código usando la clase DeviceInfo (definida en Xamarin.Essentials).
OnPlatform y OnIdiom lo usaremos en el código XAML.
Ahora veremos ejemplos de código c# y XAML de estos dos casos.

AndroidGets the Android platform.
iOSGets the iOS platform.
macOSMac OS
TizenGets the Tizen platform
tvOSGets the tvOS platform
UnknownGets the unknown platform.
UWPGets the UWP platform.
watchOSGets the watchOS platform
Tabla 1. Valores de la estructura DevicePlatform.

DesktopGets the desktop idiom.
PhoneGets the phone idiom.
TabletGets the tablet idiom.
TVGets the TV idiom.
UnknownGets the unknown idiom.
WatchGets the watch idiom.
Tabla 2. Valores de la estructura DeviceIdiom.

Código de ejemplo

Por código podemos usar DeviceInfo (habrá que importar el espacio de nombres Xamarin.Essentials) y las estructuras DevicePatform o DeviceIdiom según lo que queramos averiguar.

Nota:
En estos ejemplos estoy usando una página sencilla de tipo ContentPage de Xamarin.
En la que estarán definidos los controles usados en el código.

Por ejemplo, si queremos saber si el código está ejecutándose en un dispositivo UWP (por ejemplo, en Windows 10) o en Andoid o en iOS podemos hacer lo siguiente comprobando la propiedad Platform del tipo DeviceInfo:

// Saber la plataforma
if (DeviceInfo.Platform == DevicePlatform.UWP)
    LabelDevicePlatform.Text = "Estás usando la plataforma UWP";
else if (DeviceInfo.Platform == DevicePlatform.Android)
    LabelDevicePlatform.Text = "Estás usando la plataforma Android";
else if (DeviceInfo.Platform == DevicePlatform.iOS)
    LabelDevicePlatform.Text = "Estás usando la plataforma iOS";

Lo mismo te interesa saber si se está ejecutando en un teléfono móvil una tableta o en el escritorio, para eso usaremos la propiedad Idiom de la clase DeviceInfo:

// Saber el tipo de dispositivo
if (DeviceInfo.Idiom == DeviceIdiom.Desktop)
    LabelDeviceIdiom.Text = "Estás usando el escitorio.";
else if (DeviceInfo.Idiom == DeviceIdiom.Phone)
    LabelDeviceIdiom.Text = "Estás usando un teléfono móvil.";
else if (DeviceInfo.Idiom == DeviceIdiom.Tablet)
    LabelDeviceIdiom.Text = "Estás usando una tableta.";

Pero puede ser que lo que queremos es asignar un color según el código esté funcionando en una de las plataformas. En lugar de hacerlo por código, lo podemos hacer definiendo esa característica en el diseñador XAML.

Vamos a verlo aplicando un color al fondo de la etiqueta LabelDevicePlatform definida en el ejemplo.

<Label x:Name="LabelDevicePlatform" Padding="6"
       TextColor="White"
       BackgroundColor="{OnPlatform Android=#FA3F7E, iOS=#34C759, UWP=#0077DF}" />

En el código XAML es donde usaremos OnPlatform.

De igual forma podemos usar OnIdiom para saber el tipo de dispositivo.

<Label x:Name="LabelDeviceIdiom" Padding="6" 
       TextColor="{OnPlatform Android=Black, iOS=Blue, UWP=Green}"
       BackgroundColor="Wheat"
       FontSize="{OnIdiom Tablet=Small, Phone=Micro, Desktop=Medium}"/>

En ese código XAML hacemos las dos comprobaciones, la plataforma y el dispositivo y según sea aplicaremos un color u otro.

Si quieres hacer solo esa comprobación, por ejemplo para que en dispositivos de Apple (iOS) tengan un color y que en el resto tenga otro, podemos hacerlo de esta forma:

<Label Text="DeviceIdiom: " TextColor="{OnPlatform iOS=Green, Default=Red}"/>

En ese caso usamos el valor (o propiedad) Default que se aplicará a las plataformas (o dispositivos si se usa con OnIdiom) para las que no haya un valor concreto.

Poner varios valores en el código XAML usando OnPlatform, OnIdiom, etc.

Otra de las cosas que me ha pasado mientras estoy con esto de crear aplicaciones para dispositivos móviles y concretamente con el iPhone (iOS), en el que el texto mostrado en uno de los tipos de botones que estoy usando (para simular un Switch) es que el texto se queda pegado a los bordes del botón, mientras que en Android y UWP se quedaba separado.

Para solucionarlo necesitaba hacer dos cosas:
1- La más simple es poder añadir espacios delante y detrás del texto. Esto sería fácil si esa asignación la hago por código (c#), pero yo quería hacerla en el código de diseño (XAML).
2- Cambiar el Padding izquierdo y derecho.

El problema es que para el primer caso, tenía que asignar espacios delante y detrás del texto, pero ni usando el valor 255 (ALT+255) lo conseguí, ya que al ejecutar el código esos espacios se ignoran .

En el segundo caso, es que al asignar valores separados por comas da error, ya que después de cada coma se espera una propiedad.

Por ejemplo, lo del espacio.
Fíjate en el siguiente código XAML el valor del texto (propiedad Text) lo asigno usando un valor diferente según la plataforma.
Si es iOS uso un espacio delante y detrás de la palabra ATRÁS, en el resto de plataformas (Default) use ese mismo texto pero sin espacios:

<Button x:Name="btnAtras" 
        Text="{OnPlatform iOS= ATRÁS , Default=ATRÁS}" 
        HorizontalOptions="FillAndExpand"
        Style="{StaticResource BtnNavegar}"
        Clicked="btnAtras_Clicked"/>

Y si ese texto llevase comas, pues… ni se podría poner.

Ese sería el caso para cuando queremos asignar un valor que tenga varios argumentos separados por comas, como es el caso de Padding si no queremos asignar un solo valor para los 4 costados. Ya que solo me interesaba para la parte iaquierda y derecha, que si lo asignase de forma normal sería algo así:

Padding="6,0"

El primer valor se asignará a la izquierda y derecha (Left y Right) y el segundo valor arriba y abajo (Top y Botton).
Que queremos asignar 4 valores diferentes, lo haremos así:

Margin="4,5,6,7"

Los valores serían: 4 para la izquierda, 5 para arriba, 6 para la derecha y 7 para abajo.

La solución: Poner el texto entre comillas simples (las dobles no se pueden usar, ni siquiera usando teclas de ESCAPE, algo así: \»).

Por cierto, esa solución también es válida para el código HTML, cuando quieres poner comillas dentro de unas comillas, por ejemplo un valor style en el texto asignado a algo mediante código. Pero esa es otra historia.

Dicho lo dicho, la cosa quedaría de esta forma, si lo que se busca es que el padding izquierdo y derecho sea 6 para la plataforma iOS y 0 para el resto y que el texto incluya comas o espacios delante y/o detrás, si esos espacios están entro otros caracteres no hay que hacer nada especial.

<Label x:Name="LabelStatus" Style="{StaticResource LabelStatusWiz}"
       Padding="{OnPlatform iOS='6,0', Default=0}"
       Text="{OnPlatform Android=' Dispositivo \'Android\' ', 
                         iOS=' Dispositivo iPhone (\'iOS\') ', 
                         UWP='Dispositivo UWP (\'Windows 10, XBox\')'}"/>

Como ves el valor del Padding para iOS es ‘6,0’ (entre comillas simples).
Fíjate también que en ese código (para el valor de la propiedad Text) he usado \’ para indicar que quiero usar una comilla simple, esto solo funcionará si el texto completo está encerrado entre comillas simples.

Aquí tienes unas capturas de UWP: Windows 10 en el equipo local o lo que es lo mismo, usando el escritorio (figura 1), para Android (figura 2) y para iOS en un iPhone 7 Plus (figuras 3 y 4).

Observa los colores de las etiquetas (fondo y texto), así como en la parte de abajo que hay texto entre comillas simples.

Y observa que el padding para el botón ese con el texto tan largo, pues como que no sirve de mucho, ya que el botón pilla todo el ancho de la pantalla, pero sería útil si ese botón se está mostrando en un sitio que no lo expanda.

Si quieres, como ejercicio de práctica, puedes hacer lo siguiente:

Ejercicio 1:

Añade un panel (StackLayout) con la orientación horizontal, de esa forma los controles que metas dentro de ese stack se mostrarán uno al lado del otro, pon un Switch seguido de un botón con el texto «Un Switch» y después otro Switch y otro botón con el texto «Otro Switch» (o lo que te de la gana pero que no sea demasiado largo).
En este caso el texto no pillará todo el ancho y verás que no se ve igual en iOS / iPhone que en Android o UWP/Windows.
Si no puedes probarlos en distintos dispositivos emuladores, te pondré la respuesta con algunas capturas de los tres sistemas que utilizo con Xamarin.Forms.

Nota:
Probando el ejercicio, compruebo que el poner más espacios al final, no tienen el efecto deseado, así que… si es iOS usa el valor 6,0 para la propiedad Padding.

Otra cosa interesante que puedes hacer (ejercicio 2) es que las etiquetas estén alineadas en el centro vertical, es decir, para que no se vean con el texto tan arriba, sino en el centro de la propia etiqueta.

Pulsa en las imágenes para verlas a tamaño real.

Figura 1. El ejemplo en un Windows 10 (UWP).

Figura 2. El ejemplo en un móvil de Android (Pixel 4a).

Figura 3. El ejemplo en un móvil iOS (iPhone 7 Plus). Observa que no se ve todo el texto.

Figura 4. El ejemplo en un móvil iOS (iPhone 7 Plus).

Si miras las capturas 3 y 4 verás que en la última ya se ve bien el texto, tanto de la etiqueta de arriba como en la que tiene el fondo verde (la que indica que estás usando la plataforma iOS), para solucionar esa error, he vuelto a usar lo comentado en este post.

En el caso de la etiqueta de Xamarin he ajustado el valor de Padding para el iOS que sea más pequeño que para el resto.

<Label Text="Welcome to Xamarin.Forms!" FontSize="Title" 
       BackgroundColor="#96d1ff" Padding="{OnPlatform iOS=10,Default=40}"
       VerticalOptions="CenterAndExpand" 
       HorizontalOptions="CenterAndExpand" />

Para la etiqueta donde se muestra la plataforma en la que se está usando la aplicación, he optado por cambiar el tamaño de la letra.

<Label x:Name="LabelDevicePlatform" Padding="6"
       FontSize="{OnPlatform iOS=Micro, Default=Small}"
       TextColor="White"
       BackgroundColor="{OnPlatform Android=#FA3F7E, iOS=#34C759, UWP=#0077DF}" />

Nota importante sobre los valores asignados cuando usamos OnPlatform, OnIdiom, etc.
Cuando usamos, por ejemplo, OnPlatform el Intellisense de Visual Studio (en este ejemplo estoy usando Microsoft Visual Studio Community 2019 Version 16.10.0) te muestra los valores de la plataforma (iOS, Android, UWP, Default, etc.), pero no te muestra el intellisense para los valores asignados.
Por ejemplo, en el valor de FontSize del código XAML anterior, he usado el valor Micro para iOS y Small para el resto (Default), esos valores hay que ponerlos como se deben poner, me explico: si el valor es Micro con la m mayúscula, debe estar así escrito, si pones micro (con la m en minúscula) te dará error… Esto lo sé porque lo escribí en minúscula y al ejecutar el programa en el iPhone me dijo que nones… 😉

Si al crear un proyecto no te aparecen los emuladores ni dispositivos

Pues eso… he creado un nuevo proyecto para Xamarin.Forms para estos ejemplos y ejercicios y al intentar probarlo en otra plataforma distinta a UWP, vamos al intentar probarlo en Android o iPhone no me salían las opciones de los emuladores o los dispositivos.

¿La solución?
Cerrar la solución y volverla a abrir, así de simple.

En la página de las soluciones a los ejercicios tienes las capturas del proyecto que he creado y que está publicado en GitHub (aquí más abajo tienes el enlace).

Y esto es todo.

Solo falta publicar el proyecto en GitHub, pero como lo he usado en la aplicación que tengo para las reservas de MKN (la empresa donde trabajo), tendré que crear un proyecto/solución para poder ponerlo en GitHub y así poder descargarlo, etc.
Ya avisaré. Avisado estás de que ya está publicado en GitHub 😉
La solución a los dos ejercicios las pondré en otro post y también estarán en GitHub.

El código en GitHub

elGuille-Ejemplos

Nos vemos.
Guillermo