Créer des contrôles XAML avec C#

Cet article vous guide dans la création d’un contrôle XAML basé sur un modèle pour WinUI 3 avec C#. Les contrôles basés sur un modèle héritent de Microsoft.UI.Xaml.Controls.Control, et ont une structure visuelle et un comportement visuel qui peuvent être personnalisés à l’aide de modèles de contrôle XAML.

Pour créer des composants WinUI 3 autonomes en C# en vue de leur consommation à partir d’applications C# et C++/WinRT, consultez l’article Procédure pas à pas : Créer un composant C# avec des contrôles WinUI 3 et le consommer à partir d’une application du SDK d’application Windows C++.

Prerequisites

  1. Configurez votre environnement de développement : consultez Installer des outils pour le SDK d’application Windows.
  2. Suivez les instructions relatives à la création de votre premier projet WinUI 3.

Créer une application vide (BgLabelControlApp)

Commencez par créer un nouveau projet dans Microsoft Visual Studio. Dans la boîte de dialogue Créer un projet, sélectionnez le modèle de projet Blank App, Packaged (WinUI 3 in Desktop, en veillant à sélectionner la version de langage C#. Définissez le nom du projet sur « BgLabelControlApp » afin que les noms de fichiers correspondent au code dans les exemples ci-dessous.

Blank App Project Template

Ajouter un contrôle basé sur un modèle à votre application

Pour ajouter un contrôle basé sur un modèle, cliquez sur le menu Projet dans la barre d’outils ou cliquez avec le bouton droit sur votre projet dans l’Explorateur de solutions et sélectionnez Ajouter un nouvel élément. Sous Visual C#->WinUI, sélectionnez le modèle Contrôle personnalisé (WinUI 3). Nommez le nouveau contrôle « BgLabelControl », puis cliquez sur Ajouter.

Mettre à jour le fichier C# de contrôle personnalisé

Dans le fichier C# BgLabelControl.cs, vous voyez que le constructeur définit la propriété DefaultStyleKey pour notre contrôle. Cette clé identifie le modèle par défaut qui sera utilisé si le consommateur du contrôle ne spécifie pas explicitement un modèle. La valeur de la clé est le type du contrôle. Vous verrez comment cette clé est utilisée ultérieurement, quand nous implémenterons notre fichier de modèle générique.

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

Le contrôle basé sur un modèle aura une étiquette de texte définissable programmatiquement dans le code, en XAML, ou via une liaison de données. Pour que le système tienne à jour le texte de l’étiquette du contrôle, le contrôle doit être implémenté en tant que DependencyPropety. Pour ce faire, nous déclarons d’abord une propriété de type chaîne, que nous appelons Label. Au lieu d’utiliser une variable de stockage, nous définissons et obtenons la valeur de la propriété de dépendance en appelant GetValue et SetValue. Ces méthodes sont fournies par DependencyObject, dont Microsoft.UI.Xaml.Controls.Control hérite.

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

Ensuite, nous déclarons la propriété de dépendance et nous l’inscrivons auprès du système en appelant DependencyProperty.Register. Cette méthode spécifie le nom et le type de la propriété Label, le type du propriétaire de la propriété, la classe BgLabelControl et la valeur par défaut de la propriété.

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

Ces deux étapes suffisent pour implémenter une propriété de dépendance, mais dans cet exemple, nous allons ajouter un gestionnaire facultatif pour l’événement OnLabelChanged. Cet événement est déclenché par le système dès que la valeur de la propriété est mise à jour. Dans ce cas, nous vérifions si le nouveau texte de l’étiquette est une chaîne vide ou non, et nous mettons à jour une variable de classe en conséquence.

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;
    }
}

Pour plus d’informations sur le fonctionnement des propriétés de dépendance, consultez Vue d’ensemble des propriétés de dépendance.

Définir le style par défaut pour BgLabelControl

Un contrôle basé sur un modèle doit fournir un modèle de style par défaut qui est utilisé si le consommateur du contrôle ne définit pas explicitement un style. Dans cette étape, nous allons modifier le fichier de modèle générique pour notre contrôle.

Le fichier de modèle générique est généré quand vous ajoutez le contrôle personnalisé (WinUI) à votre application. Le fichier est nommé « Generic.xaml » et est généré dans le dossier Themes dans l’Explorateur de solutions. Les noms de dossier et de fichier sont requis pour que le framework XAML trouve le style par défaut d’un contrôle basé sur un modèle. Supprimez le contenu par défaut de Generic.xaml, puis collez le balisage ci-dessous.

<!-- \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>

Dans cet exemple, vous voyez que l’attribut TargetType de l’élément Style est défini sur le type BgLabelControl dans l’espace de noms BgLabelControlApp. Ce type est la même valeur que celle que nous avons spécifiée plus haut pour la propriété DefaultStyleKey dans le constructeur du contrôle qui l’identifie comme style par défaut du contrôle.

La propriété Text de TextBlock dans le modèle du contrôle est liée à la propriété de dépendance Label de notre contrôle. La propriété est liée à l’aide de l’extension de balisage TemplateBinding. Cet exemple lie également l’arrière-plan Grid à la propriété de dépendance Background qui est héritée de la classe Control.

Ajouter une instance de BgLabelControl à la page principale de l’interface utilisateur

Ouvrez MainWindow.xaml, qui contient le balisage XAML pour notre page d’interface utilisateur principale. Immédiatement après l’élément Button (dans StackPanel), ajoutez le balisage suivant.

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

Générez et exécutez l’application, et vous verrez le contrôle basé sur un modèle, avec la couleur d’arrière-plan et l’étiquette que nous avons spécifiés.

Templated control result

Voir aussi