[Xamarin.Forms] C# Markup Extensions

Introducción

En Xamarin.Forms 4.6 han llegado las extensiones de marcado de C#. Se trata de un conjunto (opcional) de métodos de extensión y clases auxiliares para simplificar la creación de interfaces de usuario en Xamarin.Forms usando C#. En este artículo, vamos a crear la misma interfaz usando XAML, C# y las nuevas extensiones de marcado de C# para conocer las posibilidades de las extensiones añadidas.

Crear UI con XAML

Comenzamos creando una pantalla de Login usando XAML:

<Grid
    Padding="12">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Image
        Grid.Row="0"
        BackgroundColor="Gray"
        HorizontalOptions="Center"
        VerticalOptions="Center"
        HeightRequest="100"
        WidthRequest="100"/>
    <Entry
        Grid.Row="1"
        Text="{Binding Username, Mode=TwoWay}"
        Placeholder="Username"/>
    <Entry
        Grid.Row="2"
        Text="{Binding Password, Mode=TwoWay}"
        IsPassword="True"
        Placeholder="Password"/>
    <Label
        Grid.Row="3"
        Text="Forgot Password?"
        FontSize="Micro"
        TextDecorations="Underline"
        HorizontalOptions="End"/>
    <Grid
        Grid.Row="4">
        <Button
            BackgroundColor="White"
            CornerRadius="24"
            Text="LOGIN"
            HeightRequest="60"
            VerticalOptions="Center"
            Command="{Binding SignInCommand}"
            Margin="24, 12"/>
    </Grid>
</Grid>

Crear UI con C#

Vamos a crear lo mismo usando C#:

public class LoginCSharpView : ContentPage
{
    public LoginCSharpView()
    {
        BindingContext = new LoginViewModel();
        BackgroundColor = Color.LightGray;

        var grid = new Grid
        {
            Padding = 12
        };

        grid.RowDefinitions.Add(new RowDefinition());
        grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
        grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
        grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
        grid.RowDefinitions.Add(new RowDefinition());

        var logo = new Image
        {
            BackgroundColor = Color.Gray,
            HeightRequest = 100,
            WidthRequest = 100,
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        };

        grid.Children.Add(logo);
        Grid.SetRow(logo, 0);

        var usernameEntry = new Entry
        {
            Placeholder = "Username"
        };
        usernameEntry.SetBinding(Entry.TextProperty, "Username");
        grid.Children.Add(usernameEntry);
        Grid.SetRow(usernameEntry, 1);

        var passwordEntry = new Entry
        {
            IsPassword = true,
            Placeholder = "Password"
        };
        passwordEntry.SetBinding(Entry.TextProperty, "Password");
        grid.Children.Add(passwordEntry);
        Grid.SetRow(passwordEntry, 2);

        var forgotPassword = new Label
        {
            FontSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label)),
            Text = "Forgot Password?",
            TextDecorations = TextDecorations.Underline,
            HorizontalOptions = LayoutOptions.End
        };
        grid.Children.Add(forgotPassword);
        Grid.SetRow(forgotPassword, 3);

        var signInGrid = new Grid();

        var signInButton = new Button
        {
            BackgroundColor = Color.White,
            CornerRadius = 24,
            HeightRequest = 60,
            Margin = new Thickness(24, 12),
            VerticalOptions = LayoutOptions.Center,
            Text = "LOGIN"
        };
        signInGrid.Children.Add(signInButton);

        grid.Children.Add(signInGrid);
        Grid.SetRow(signInGrid, 4);

        Content = grid;
    }
}

C# Markup Extensions

Pasamos a ver las novedades aportadas por las extensiones añadidas:

public class LoginCSharpMarkupView : ContentPage
{
    enum Row { Logo, Username, Password, Forgot, SignIn };

    public LoginCSharpMarkupView()
    {
        var vm = new LoginViewModel();
        BindingContext = vm;
        BackgroundColor = Color.LightGray;

        Content = new Grid
        {
            Padding = 12,
            RowDefinitions = Rows.Define(
                (Row.Logo, GridLength.Star),
                (Row.Username, GridLength.Auto),
                (Row.Password, GridLength.Auto),
                (Row.Forgot, GridLength.Auto),
                (Row.SignIn, GridLength.Star)),
            Children =
            {
                new Image
                {
                    BackgroundColor = Color.Gray,
                    HeightRequest = 100,
                    WidthRequest = 100,
                    HorizontalOptions = LayoutOptions.Center,
                    VerticalOptions = LayoutOptions.Center
                }.Row(Row.Logo),
                new Entry
                {
                    Placeholder = "Username"
                }.Row(Row.Username).Bind(nameof(vm.Username)),
                new Entry
                {
                    IsPassword = true,
                    Placeholder = "Password"
                }.Row(Row.Password).Bind(nameof(vm.Password)),
                new Label
                {
                    FontSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label)),
                    Text = "Forgot Password?",
                    TextDecorations = TextDecorations.Underline,
                    HorizontalOptions = LayoutOptions.End
                }.Row(Row.Forgot),
                new Button
                {
                    BackgroundColor = Color.White,
                    CornerRadius = 24,
                    HeightRequest = 60,
                    Margin = new Thickness(24, 12),
                    VerticalOptions = LayoutOptions.Center,
                    Text = "LOGIN"
                }.Row(Row.SignIn).Bind(nameof(vm.SignInCommand))
            }
        };
    }
}

Antes de profundizar en detalles, las extensiones de marcado C# añadidas en Xamarin.Forms 4.6 se encuentran en fase experimental:

Device.SetFlags(new string[]{ "Markup_Experimental" });

Las extensiones para crear la interfaz de usuario usando C# de forma  fluida se encuentran en el espacio de nombres Xamarin.Forms.Markup.

Enlace a datos

Contamos con el método de extension Bind que cuenta con varias sobrecargas para crear un enlace de datos entre la propiedad de una vista y una propiedad especificada.

var password = new Entry { IsPassword = true, Placeholder = "Password" }.Bind(nameof(vm.Password));

Layouts

Al usar un Grid, podemos usar una enumeración para definir filas y columnas, en lugar de usar directamente números. Es necesario utilizar el namespace:

using static Xamarin.Forms.Markup.GridRowsColumns;

Veamos el uso:

var grid = new Grid { 
     RowDefinitions = 
          Rows.Define( (Row.Logo, GridLength.Star), (Row.Username, GridLength.Auto), (Row.Password, GridLength.Auto), (Row.Forgot, GridLength.Auto), (Row.SignIn, GridLength.Star))
};

Además, se puede definir de forma sencilla filas y columnas usando la enumeración:

var password = new Entry { IsPassword = true, Placeholder = "Password" }.Row(Row.Password);

Estilos

Los estilos implícitos se pueden utilizar cargándolos en el diccionario de recursos de la aplicación:

public App()
{
     Resources = Styles.Implicit;
     ...
}

Mientras que los estilos explícitos se pueden usar utilizando el método de extensión Style.

var password = new Entry { IsPassword = true, Placeholder = "Password" }.Style (PasswordStyle);

Otros

Aunque no lo hemos visto en el ejemplo de Login, tenemos bastantes mas extensiones para trabajar con fuentes, efectos, gestos, etc.

Para trabajar con gestos podemos usar el método de extensión BindTapGesture:

var tapLabel = new Label { Text = "Tap Me" } .BindTapGesture (nameof(vm.TapCommand));

Podemos adjuntar efectos usando el método de extensión Effects:

var effectButton = new Button { Text = "Tap Me" }.Effects (new ButtonBordeless());

Para ver más ejemplos y detalles relacionados con las extensiones de marcado, puedes leer la documentación oficial.

Puedes encontrar el ejemplo en GitHub:

Ver GitHub

¿Qué te parecen las extensiones de marcado C#?, ¿creas la interfaz de usuario en Xamarin.Forms usando XAML o C#). Recuerda, puedes dejar cualquier duda o comentario en la entrada!.

Más información

[Material] Seville Microsoft Communities Day

microsoft_.net_logoEl evento

El pasado 09 de Marzo, aprovechando la visita de miembros del equipo de DX de Microsoft para el University Tour 2016, como Alejandro Campos, las comunidades .NET de Sevilla decidimos organizar un divertido evento el día anterior, el Seville Microsoft Communities Day. Un evento donde tener hueco a sesiones técnicas sobre C# y Xamarin además de tener momentos para el networking y dar a conocer todas las comunidades.

Tenéis disponible una pequeña galería del evento a continuación:

El material

En mi caso pude participar en el evento junto a Marcos Cobeña con una introducción completa a Xamarin, desarrollo, herramientas y servicios. Vimos:

  • Desarrollo con Xamarin Classic.
  • Desarrollo con Xamarin Forms.
  • Un vistazo tanto a la integración con Visual Studio como a Xamarin Studio.
  • Herramientas como Xamarin Inspector.
  • Xamarin UITests y Xamarin Test Cloud.
  • Xamarin Insights.

Además se comentaron los últimos movimientos importantes como la compra de Xamarin por parte de Microsoft y las siguientes fechas de peso, //BUILD 2016 y Evolve 2016. El objetivo final era que todos los asistentes conocieran el aporte de Xamarin desde las herramientas al desarrollo pasando por sus servicios.

La presentación utilizada la tenéis disponible en este enlace. En cuanto a las demos técnicas realizadas, las tenéis disponible en GitHub:

Ver GitHub

Quisiera terminar añadiendo algunos agradecimientos a Alejandro Campos y Marcos Cobeña por participar junto a un servidor en las sesiones, gracias a todas las comunidades .NET de Sevilla y por supuesto, muchas gracias a todos los asistentes.

Más información

Seville Microsoft Communities Day

hero-estuUniversity Tour 2016

El próximo 10 de Marzo en la Escuela Superior de Informática de Sevilla tiene lugar el University Tour 2016. Un evento diseñado tanto para estudiantes como para profesores donde se enseñan las tecnologías que más se usan a día de hoy. Aspectos como la gestión del ciclo de vida del software con metodologías ágiles, como hacer un desarrollo para todas las plataformas móviles que se usan actualmente, o como aprovechar todos los recursos que la nube pone a nuestra disposición.

Comunidades técnicas .NET Sevilla

En Sevilla contamos con grandes profesionales y empresas focalizadas en el trabajo en diferentes vertientes utilizando .NET y tecnologías Microsoft. No es de extrañar, que ante tantas variedades, inquietudes y opciones se cuente con una gran diversidad de comunidades técnicas relacionadas con tecnologías Microsoft.

El evento

El día 09 de Marzo las comunidades técnicas .NET de Sevilla aprovechando la presencia de compañeros de DX de Microsoft, vamos a organizar un evento con la siguiente agenda:

• 19:00h – 20:15h Pero… C# no es un lenguaje de programación funcional, ¿verdad? por Alejandro Campos.

C# es un lenguaje de programación multi-paradigma que soporta expresiones lambda desde el año 2007, y al que se le han ido añadiendo muchas características de programación funcional durante los últimos 10 años. Conoce C# 6.0, y cómo se ha convertido en uno de los mejores lenguajes de programación gracias a todas estas características. Aunque lleves años desarrollando con este lenguaje, esta sesión puede cambiarte la manera de utilizarlo de ahora en adelante.

• 20:15h – 21:00h Creando aplicaciones multiplataforma con Xamarin por Javier Suárez y Marcos Cobeña.

En esta sesión conoceremos todas las posibilidades que ofrece Xamarin para crear aplicaciones móviles nativas multiplataforma. Además, revisaremos principales herramientas y servicios destinados a mejorar nuestra productividad o búsqueda de la calidad.

¿Te apuntas?

El lugar

El evento se celebrará en la ETS de Ingeniería Informática. Dirección detallada:

E.T.S. Ingeniería Informática – Universidad de Sevilla
Av. Reina Mercedes s/n
Sevilla Se 41012

ETS de Ingeniería Informática

ETS de Ingeniería Informática

Más información