ContentView de Xamarin.Forms

La clase Xamarin.FormsContentView es un tipo de Layout que contiene un único elemento secundario y se usa normalmente para crear controles personalizados y reutilizables. La clase ContentView se hereda de TemplatedView. En este artículo, y en el ejemplo correspondiente, se explica cómo crear un control CardView personalizado basado en la clase ContentView.

En la captura de pantalla siguiente se muestra un control CardView que se deriva de la clase ContentView:

Captura de pantalla de la aplicación de ejemplo CardView

La clase ContentView define una sola propiedad:

  • Content es un objeto View. Esta propiedad está respaldada por un objeto BindableProperty para que pueda ser el destino de los enlaces de datos.

ContentView también hereda una propiedad de la clase TemplatedView:

  • ControlTemplate es un ControlTemplate que puede definir o invalidar la apariencia del control.

Para obtener más información sobre la propiedad ControlTemplate, consulta Personalización de la apariencia con ControlTemplate.

Creación de un control personalizado

La clase ContentView ofrece poca funcionalidad por sí misma, pero se puede usar para crear un control personalizado. El proyecto de ejemplo define un control CardView: un elemento de interfaz de usuario que muestra una imagen, un título y una descripción en un diseño similar a una tarjeta.

El proceso para crear un control personalizado es para:

  1. Cree una nueva clase usando la plantilla ContentView en Visual Studio 2019.
  2. Defina las propiedades o eventos únicos del archivo de código subyacente para el nuevo control personalizado.
  3. Cree la interfaz de usuario para el control personalizado.

Nota:

Es posible crear un control personalizado cuyo diseño se defina en código en lugar de hacerlo con XAML. Por motivos de simplicidad, la aplicación de ejemplo solo define una sola clase CardView con un diseño XAML. Sin embargo, la aplicación de ejemplo contiene una clase CardViewCodePage que muestra el proceso de consumo del control personalizado en el código.

Creación de propiedades de código subyacente

El control personalizado CardView define las siguientes propiedades:

  • CardTitle: un objeto string que representa el título que se muestra en la tarjeta.
  • CardDescription: un objeto string que representa la descripción que se muestra en la tarjeta.
  • IconImageSource: un objeto ImageSource que representa la imagen que se muestra en la tarjeta.
  • IconBackgroundColor: un objeto Color que representa el color de fondo de la imagen que se muestra en la tarjeta.
  • BorderColor: un objeto Color que representa el color del borde de la tarjeta, el borde de imagen y la línea divisora.
  • CardColor: un objeto Color que representa el color de fondo de la tarjeta.

Nota:

La propiedad BorderColor afecta a varios elementos con fines de demostración. Esta propiedad podría dividirse en tres propiedades si es necesario.

Cada propiedad está respaldada por una instancia de BindableProperty. La BindableProperty de respaldo permite aplicar un estilo a cada propiedad y enlazarla mediante el patrón MVVM.

En el ejemplo siguiente se muestra cómo crear una BindableProperty de respaldo:

public static readonly BindableProperty CardTitleProperty = BindableProperty.Create(
    "CardTitle",        // the name of the bindable property
    typeof(string),     // the bindable property type
    typeof(CardView),   // the parent object type
    string.Empty);      // the default value for the property

La propiedad personalizada usa los métodos GetValue y SetValue para obtener y establecer los valores del objeto BindableProperty:

public string CardTitle
{
    get => (string)GetValue(CardView.CardTitleProperty);
    set => SetValue(CardView.CardTitleProperty, value);
}

Para obtener más información sobre los objetos BindableProperty, consulte Propiedades enlazables.

Definición de la interfaz de usuario

La interfaz de usuario de control personalizada usa ContentView como elemento raíz para el control CardView. En el ejemplo siguiente se muestra el XAML de CardView:

<ContentView ...
             x:Name="this"
             x:Class="CardViewDemo.Controls.CardView">
    <Frame BindingContext="{x:Reference this}"
            BackgroundColor="{Binding CardColor}"
            BorderColor="{Binding BorderColor}"
            ...>
        <Grid>
            ...
            <Frame BorderColor="{Binding BorderColor, FallbackValue='Black'}"
                   BackgroundColor="{Binding IconBackgroundColor, FallbackValue='Grey'}"
                   ...>
                <Image Source="{Binding IconImageSource}"
                       .. />
            </Frame>
            <Label Text="{Binding CardTitle, FallbackValue='Card Title'}"
                   ... />
            <BoxView BackgroundColor="{Binding BorderColor, FallbackValue='Black'}"
                     ... />
            <Label Text="{Binding CardDescription, FallbackValue='Card description text.'}"
                   ... />
        </Grid>
    </Frame>
</ContentView>

El elemento ContentView establece la propiedad x:Name en this, que se puede usar para acceder al objeto enlazado a la instancia CardView. Los elementos del conjunto de diseño enlazan sus propiedades a los valores definidos en el objeto enlazado.

Para obtener más información sobre el enlace de datos, consulte Enlace de datos de Xamarin.Forms.

Nota:

La propiedad FallbackValue proporciona un valor predeterminado en caso de que el enlace sea null. Esto también permite que el controlador de vista previa XAML de Visual Studio represente el control CardView.

Creación de instancias de un control personalizado

Se debe agregar una referencia al espacio de nombres de control personalizado a una página que cree una instancia del control personalizado. En el ejemplo siguiente se muestra una referencia de espacio de nombres denominada controls que se agrega a una instancia de ContentPage en XAML:

<ContentPage ...
             xmlns:controls="clr-namespace:CardViewDemo.Controls" >

Una vez agregada la referencia, se puede crear una instancia de CardView en XAML y se pueden definir sus propiedades:

<controls:CardView BorderColor="DarkGray"
                   CardTitle="Slavko Vlasic"
                   CardDescription="Lorem ipsum dolor sit..."
                   IconBackgroundColor="SlateGray"
                   IconImageSource="user.png"/>

También se puede crear una instancia de CardView en el código:

CardView card = new CardView
{
    BorderColor = Color.DarkGray,
    CardTitle = "Slavko Vlasic",
    CardDescription = "Lorem ipsum dolor sit...",
    IconBackgroundColor = Color.SlateGray,
    IconImageSource = ImageSource.FromFile("user.png")
};

Personalización de la apariencia con ControlTemplate

Un control personalizado que deriva de la clase ContentView puede definir la apariencia mediante XAML, código o puede que no defina la apariencia en absoluto. Independientemente de cómo se defina la apariencia, un objeto ControlTemplate puede invalidar la apariencia con un diseño personalizado.

El diseño CardView puede ocupar demasiado espacio para algunos casos de uso. Un ControlTemplate puede invalidar el diseño CardView para proporcionar una vista más compacta, adecuada para una lista condensada:

<ContentPage.Resources>
    <ResourceDictionary>
        <ControlTemplate x:Key="CardViewCompressed">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="100" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="100*" />
                </Grid.ColumnDefinitions>
                <Image Grid.Row="0"
                       Grid.Column="0"
                       Source="{TemplateBinding IconImageSource}"
                       BackgroundColor="{TemplateBinding IconBackgroundColor}"
                       WidthRequest="100"
                       HeightRequest="100"
                       Aspect="AspectFill"
                       HorizontalOptions="Center"
                       VerticalOptions="Center"/>
                <StackLayout Grid.Row="0"
                             Grid.Column="1">
                    <Label Text="{TemplateBinding CardTitle}"
                           FontAttributes="Bold" />
                    <Label Text="{TemplateBinding CardDescription}" />
                </StackLayout>
            </Grid>
        </ControlTemplate>
    </ResourceDictionary>
</ContentPage.Resources>

El enlace de datos de ControlTemplate usa la extensión de marcado TemplateBinding para especificar enlaces. A continuación, la propiedad ControlTemplate se puede establecer en el objeto ControlTemplate definido usando su valor x:Key. En el siguiente ejemplo se muestra la propiedad ControlTemplate establecida en la instancia CardView:

<controls:CardView ControlTemplate="{StaticResource CardViewCompressed}"/>

Las capturas de pantalla siguientes muestran una instancia estándar de CardView y CardView cuyo ControlTemplate se ha invalidado:

Captura de pantalla de CardView ControlTemplate

Para obtener más información sobre las plantillas de control, consulte Plantillas de control de Xamarin.Forms.