Compilación de controles XAML con C#

En este artículo se recorren los pasos para la creación de un control XAML con plantilla para WinUI 3 con C#. Los controles con plantilla se heredan de Microsoft.UI.Xaml.Controls.Control y tienen una estructura y comportamiento visual que se pueden personalizar mediante plantillas de control XAML.

Para crear componentes independientes de WinUI 3 en C# para su consumo desde aplicaciones de C# y C++/WinRT, consulte el artículo Tutorial: Creación de un componente de C# con controles de WinUI 3 y consumirlo desde una aplicación del SDK para aplicaciones de Windows C++.

Prerrequisitos

  1. Configuración del entorno de desarrollo: consulte Instalación de herramientas para el SDK de Aplicaciones para Windows.
  2. Siga las instrucciones sobre cómo Crear el primer proyecto de WinUI 3.

Crear una aplicación en blanco (BgLabelControlApp)

Para empezar, crea un proyecto en Microsoft Visual Studio. En el cuadro de diálogo Crear un proyecto, seleccione la plantilla de proyecto Aplicación vacía (WinUI 3 en Escritorio) y asegúrese de seleccionar la versión de lenguaje C#. Establezca el nombre del proyecto en "BgLabelControlApp" para que los nombres de archivo se alineen con el código en los ejemplos siguientes.

Blank App Project Template

Adición de un control con plantilla a la aplicación

Para agregar un control con plantilla, haga clic en el menú Proyecto de la barra de herramientas o haga clic con el botón derecho en el proyecto en Explorador de soluciones y seleccione Agregar nuevo elemento. En Visual C#->WinUI, seleccione la plantilla Control personalizado (WinUI 3). Asigne al nuevo control el nombre "BgLabelControl" y haga clic en Agregar.

Actualización del archivo de C# de control personalizado

En el archivo de C#, BgLabelControl.cs, tenga en cuenta que el constructor define la propiedad DefaultStyleKey para el control. Esta clave identifica la plantilla predeterminada que se usará si el consumidor del control no especifica explícitamente ninguna plantilla. El valor de clave es el tipo de nuestro control. Veremos esta clave en uso más adelante cuando implementemos el archivo de plantilla genérico.

public BgLabelControl()
{
    this.DefaultStyleKey = typeof(BgLabelControl);
}

Nuestro control con plantilla tendrá una etiqueta de texto que se puede establecer mediante programación en el código, en XAML o mediante el enlace de datos. Para que el sistema mantenga actualizado el texto de la etiqueta del control, es necesario implementarlo como DependencyPropety. Para ello, primero declaramos una propiedad de cadena y la denominamos Label. En lugar de usar una variable alternativa, establecemos y obtenemos el valor de nuestra propiedad de dependencia mediante una llamada a GetValue y SetValue. Estos métodos los proporciona DependencyObject, que hereda el elemento Microsoft.UI.Xaml.Controls.Control.

public string Label
{
    get => (string)GetValue(LabelProperty);
    set => SetValue(LabelProperty, value);
}

A continuación, declare la propiedad de dependencia y regístrela en el sistema mediante una llamada a DependencyProperty.Register. Este método especifica el nombre y el tipo de la propiedad Label, el tipo de propietario de la propiedad, nuestra clase BgLabelControl y el valor predeterminado de la propiedad.

DependencyProperty LabelProperty = DependencyProperty.Register(
    nameof(Label), 
    typeof(string),
    typeof(BgLabelControl), 
    new PropertyMetadata(default(string), new PropertyChangedCallback(OnLabelChanged)));

Estos dos pasos son todos necesarios para implementar una propiedad de dependencia, pero, en este ejemplo, vamos a agregar un controlador opcional para el evento OnLabelChanged. El sistema genera este evento cada vez que se actualiza el valor de la propiedad. En este caso, comprobamos si el nuevo texto de etiqueta es una cadena vacía o no y actualizamos una variable de clase según corresponda.

public bool HasLabelValue { get; set; }

private static void OnLabelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    BgLabelControl labelControl = d as BgLabelControl; //null checks omitted
    String s = e.NewValue as String; //null checks omitted
    if (s == String.Empty)
    {
        labelControl.HasLabelValue = false;
    }
    else
    {
        labelControl.HasLabelValue = true;
    }
}

Si quiere obtener más información acerca de cómo funcionan las propiedades de dependencia, consulte Introducción a las propiedades de dependencia.

Diseño del estilo predeterminado para BgLabelControl

Un control con plantilla debe proporcionar una plantilla de estilo predeterminada que se utilice si el usuario del control no establece explícitamente un estilo. En este paso, modificaremos el archivo de plantilla genérico para el control.

El archivo de plantilla genérico se genera cuando se agrega el Control personalizado (WinUI) a la aplicación. El archivo se denomina "Generic.xaml" y se genera en la carpeta Themes del Explorador de soluciones. Los nombres de carpeta y archivo son obligatorios para que el marco XAML encuentre el estilo predeterminado para un control con plantilla. Elimine el contenido predeterminado de Generic.xaml y péguelo en el siguiente marcado.

<!-- \Themes\Generic.xaml -->
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:BgLabelControlApp">

    <Style TargetType="local:BgLabelControl" >
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:BgLabelControl">
                    <Grid Width="100" Height="100" Background="{TemplateBinding Background}">
                        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{TemplateBinding Label}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

En este ejemplo, puede ver que el atributo TargetType del elemento Style está establecido en el tipo BgLabelControl del espacio de nombres BgLabelControlApp. Este tipo es el mismo valor que especificamos anteriormente para la propiedad DefaultStyleKey en el constructor del control, que lo identifica como el estilo predeterminado del control.

La propiedad Text de TextBlock de la plantilla de control está enlazada a la propiedad de dependencia Label del control. La propiedad se enlaza mediante la extensión de marcado TemplateBinding. En este ejemplo también se enlaza el fondo Grid a la propiedad de dependencia Background que se hereda de la clase Control.

Adición de una instancia de BgLabelControl a la página principal de la interfaz de usuario

Abre MainWindow.xaml, que contiene el marcado XAML de nuestra página principal de la interfaz de usuario. Inmediatamente después del elemento Button (dentro de la clase StackPanel), agrega el marcado siguiente.

<local:BgLabelControl Background="Red" Label="Hello, World!"/>

Compile y ejecute la aplicación y verá el control con plantilla, con el color de fondo y la etiqueta especificados.

Templated control result

Consulte también