Utiliser XAML Islands pour héberger un contrôle XAML UWP dans une application WPF C#

Important

Cette rubrique utilise ou mentionne des types du dépôt GitHub CommunityToolkit/Microsoft.Toolkit.Win32. Pour obtenir des informations importantes sur la prise en charge de XAML Islands, consultez l’avis XAML Islands dans ce dépôt.

Cette rubrique explique comment créer une application WPF (Windows Presentation Foundation) C# qui cible .NET Core 3.1, et utilise XAML Islands pour héberger un contrôle XAML UWP (Universal Windows Platform), qui est un contrôle interne fourni par le SDK Windows. Nous montrons deux façons possibles de le faire :

  • Nous montrons comment héberger les contrôles InkCanvas et InkToolbar UWP en utilisant des contrôles wrappés (disponibles dans le kit de ressources Windows Community Toolkit). Les contrôles wrappés wrappent l’interface et les fonctionnalités d’un petit ensemble de contrôles XAML UWP utiles. Vous pouvez ajouter un contrôle wrappé directement à l’aire de conception de votre projet WPF ou Windows Forms, puis l’utiliser dans le concepteur comme tout autre contrôle WPF ou Windows Forms.

  • Nous montrons aussi comment héberger un contrôle CalendarView UWP en utilisant le contrôle WindowsXamlHost (disponible dans le kit de ressources Windows Community Toolkit). Seul un petit ensemble de contrôles XAML UWP étant disponible sous forme de contrôles wrappés, vous pouvez utiliser WindowsXamlHost pour héberger n’importe quel contrôle XAML UWP.

Le processus d’hébergement d’un contrôle XAML UWP dans une application WPF est similaire pour une application Windows Forms.

Important

L’utilisation de XAML Islands (contrôles wrappés ou WindowsXamlHost) pour héberger les contrôles XAML UWP est prise en charge uniquement dans les applications qui ciblent .NET Core 3.x. XAML Islands n’est pas pris en charge dans les applications ciblant .NET ou toute version du .NET Framework.

Pour l’hébergement de contrôles XAML UWP dans une application WPF ou Windows Forms, nous vous recommandons d’inclure les composants suivants dans votre solution. Cette rubrique fournit des instructions sur la création de chacun de ces composants :

  • Le projet et le code source de votre application WPF ou Windows Forms.

  • Un projet UWP qui définit une classe Application racine dérivant de XamlApplication. La classe Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication est disponible dans le kit de ressources Windows Community Toolkit). Nous vous recommandons de définir votre classe Application dérivée de XamlApplication en tant que projet d’application UWP distinct dans votre solution WPF ou Windows Forms dans Visual Studio.

    Note

    Il n’est pas obligatoire de rendre un objet dérivé de XamlApplication disponible dans votre projet WPF ou Windows Forms pour héberger un contrôle XAML UWP. En revanche, cela est obligatoire pour découvrir, charger et héberger des contrôles XAML UWP personnalisés. Aussi, pour assurer la prise en charge de l’ensemble des scénarios XAML Islands, nous vous recommandons de toujours définir un objet dérivé de XamlApplicationdans toute solution où vous utilisez XAML Islands.

    Note

    Votre solution ne peut contenir qu’un seul projet qui définit un objet dérivé de XamlApplication. Cet unique projet doit référencer tous les autres projets et bibliothèques qui hébergent des contrôles XAML UWP par le biais de XAML Islands.

Créer un projet WPF

Aidez-vous des instructions suivantes pour créer un projet WPF et le configurer en vue de l’hébergement de XAML Islands. Si vous avez déjà un projet WPF, adaptez les étapes et les exemples de code indiqués selon votre projet.

  1. Si vous ne l’avez pas déjà fait, installez la dernière version de .NET Core 3.1.

  2. Dans Visual Studio, créez un projet C# à partir du modèle de projet Application WPF. Définissez Nom du projet sur MyWPFApp, ce qui vous évitera d’avoir à adapter les étapes ou le code source de cette rubrique. Définissez Framework sur .NET Core 3.1*, puis cliquez sur Créer.

Important

N’utilisez pas le modèle de projet Application WPF (.NET Framework).

Configurer votre projet WPF

  1. Ces étapes activent les références de package :

    1. Dans Visual Studio, cliquez sur Outils>Gestionnaire de package NuGet>Paramètres du Gestionnaire de package.
    2. Sur la droite, recherchez le paramètre Package Management>Format de gestion des packages par défaut et définissez-le sur PackageReference.
  2. Effectuez ces étapes pour installer le package NuGet Microsoft.Toolkit.Wpf.UI.Controls :

    1. Cliquez avec le bouton droit sur le nœud de projet MyWPFApp dans l’Explorateur de solutions, puis choisissez Gérer les packages NuGet....

    2. Sous l’onglet Parcourir, tapez ou collez Microsoft.Toolkit.Wpf.UI.Controls dans la zone de recherche. Sélectionnez la dernière version stable disponible, puis cliquez sur Installer. Ce package fournit tout ce dont vous avez besoin pour utiliser les contrôles XAML UWP wrappés pour WPF (y compris InkCanvas, InkToolbar et le contrôle WindowsXamlHost).

    Note

    Pour une application Windows Forms, référencez le package Microsoft.Toolkit.Forms.UI.Controls à la place.

  3. La majorité des scénarios XAML Islands ne sont pas pris en charge dans les projets qui ciblent N’importe quel processeur. Pour cibler une architecture spécifique (par exemple, x86 ou x64), procédez comme suit :

    1. Cliquez avec le bouton droit sur le nœud de la solution (pas sur le nœud du projet) dans l’Explorateur de solutions, puis choisissez Propriétés.
    2. Sélectionnez Propriétés de configuration sur la gauche.
    3. Cliquez sur le bouton Configuration Manager....
    4. Sous Plateforme de la solution active, sélectionnez Nouveau.
    5. Dans la boîte de dialogue Nouvelle plateforme de solution, sélectionnez x64 ou x86, puis appuyez sur OK.
    6. Fermez les boîtes de dialogue ouvertes.

Définir une classe XamlApplication dans un nouveau projet UWP

Dans cette section, nous allons ajouter un projet UWP à la solution, puis modifier la classe App par défaut dans ce projet afin de la dériver de la classe Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication, qui est fournie dans le kit de ressources Windows Community Toolkit. Cette classe prend en charge l’interface IXamlMetadataProvider, qui permet à votre application de découvrir et de charger des métadonnées pour les contrôles XAML UWP personnalisés dans les assemblys du répertoire actif de votre application au moment de l’exécution. Cette classe initialise également le framework XAML UWP pour le thread actuel.

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nœud de la solution, puis sélectionnez Ajouter>Nouveau projet....

  2. Sélectionnez le modèle de projet Application vide (Windows universel) C#. Définissez Nom du projet sur MyUWPApp, ce qui vous évitera d’avoir à adapter les étapes ou le code source de cette rubrique. Définissez Version cible et Version minimale sur Windows 10, version 1903 (Build 18362) ou une version ultérieure.

    Note

    Ne créez pas MyUWPApp dans un sous-dossier de MyWPFApp. Sinon, MyWPFApp essaiera de générer le balisage XAML UWP comme s’il s’agissait d’un balisage XAML WPF.

  3. Dans MyUWPApp, installez le package NuGet Microsoft.Toolkit.Win32.UI.XamlApplication (la dernière version stable). Le processus d’installation d’un package NuGet a été décrit dans la section précédente.

  4. Dans MyUWPApp, ouvrez le fichier App.xaml et remplacez son contenu par le code XAML suivant :

    <xaml:XamlApplication
        x:Class="MyUWPApp.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:xaml="using:Microsoft.Toolkit.Win32.UI.XamlHost"
        xmlns:local="using:MyUWPApp">
    </xaml:XamlApplication>
    
  5. De la même façon, ouvrez App.xaml.cs et remplacez son contenu par le code suivant :

    namespace MyUWPApp
    {
        public sealed partial class App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
        {
            public App()
            {
                this.Initialize();
            }
        }
    }
    
  6. Supprimez les fichiers MainPage.xaml et MainPage.xaml.cs.

  7. Générez le projet MyUWPApp.

Dans MyWPFApp, ajoutez une référence au projet MyUWPApp

  1. Spécifiez la version de framework compatible dans le fichier projet MyWPFApp, comme ceci :

    1. Dans l’Explorateur de solutions, cliquez sur le nœud de projet MyWPFApp pour ouvrir le fichier projet dans l’éditeur.

    2. Dans le premier élément PropertyGroup, ajoutez l’élément enfant suivant. Modifiez la partie 19041 de la valeur si nécessaire, pour qu’elle corresponde à la version de système d’exploitation cible et minimale du projet MyWPFApp.

      <AssetTargetFallback>uap10.0.19041</AssetTargetFallback>
      
  2. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur MyWPFApp>Dépendances, choisissez Ajouter une référence de projet..., puis ajoutez une référence au projet MyUWPApp.

Instancier l’objet XamlApplication dans le point d’entrée de MyWPFApp

Ensuite, ajoutez du code au point d’entrée de MyWPFApp pour créer une instance de la classe App que vous venez de définir dans MyUWPApp (il s’agit de la classe qui dérive de XamlApplication).

  1. Cliquez avec le bouton droit sur le nœud du projet MyWPFApp, sélectionnez Ajouter>Nouvel élément..., puis sélectionnez Classe. Définissez Nom sur Program.cs, puis cliquez sur Ajouter.

  2. Remplacez le contenu de Program.cs par le code XAML suivant (puis enregistrez le fichier et générez le projet MyWPFApp) :

    namespace MyWPFApp
    {
        public class Program
        {
            [System.STAThreadAttribute()]
            public static void Main()
            {
                using (new MyUWPApp.App())
                {
                    var app = new MyWPFApp.App();
                    app.InitializeComponent();
                    app.Run();
                }
            }
        }
    }
    
  3. Cliquez avec le bouton droit sur le nœud du projet MyWPFApp, puis choisissez Propriétés.

  4. Dans Application>Général, cliquez sur la liste déroulante Objet de démarrage, puis choisissez MyWPFApp.Program (qui est le nom complet de la classe Program que vous venez d’ajouter). Si vous ne voyez pas cette entrée, essayez de fermer et de rouvrir Visual Studio.

    Note

    Par défaut, un projet WPF définit une fonction de point d’entrée Main dans un fichier de code généré qui n’est pas destiné à être modifié. L’étape ci-dessus remplace le point d’entrée de votre projet par la méthode Main de la nouvelle classe Program, ce qui vous permet d’ajouter du code qui s’exécute aussi tôt que possible dans le processus de démarrage de l’application.

  5. Enregistrez les modifications apportées aux propriétés du projet.

Utiliser des contrôles wrappés pour héberger les contrôles InkCanvas et InkToolbar

Votre projet étant configuré pour utiliser UWP XAML Islands, vous pouvez ajouter à l’application les contrôles UWP wrappés InkCanvas et InkToolbar.

  1. Dans MyWPFApp, ouvrez le fichier MainWindow.xaml.

  2. Dans l’élément Window vers le début du fichier XAML, ajoutez l’attribut suivant. Cet attribut référence l’espace de noms XAML pour les contrôles XAML UWP wrappés InkCanvas et InkToolbar, et le mappe à l’espace de noms XML controls.

    xmlns:controls="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls"
    
  3. Toujours dans MainWindow.xaml, modifiez l’élément Grid existant selon le code XAML ci-dessous. Ce code XAML ajoute à l’élément Grid un contrôle InkCanvas et un contrôle InkToolbar (préfixés par l’espace de noms XML controls que vous avez défini à l’étape précédente).

    <Grid Margin="10,50,10,10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <controls:InkToolbar x:Name="myInkToolbar" TargetInkCanvas="{x:Reference myInkCanvas}" Grid.Row="0" Width="300"
            Height="50" Margin="10,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top" />
        <controls:InkCanvas x:Name="myInkCanvas" Grid.Row="1" HorizontalAlignment="Left" Width="600" Height="400"
            Margin="10,10,10,10" VerticalAlignment="Top" />
    </Grid>
    

    Note

    Vous pouvez également ajouter ces contrôles et d’autres contrôles wrappés à l’élément Window en les faisant glisser vers le concepteur depuis la section Windows Community Toolkit de la Boîte à outils.

  4. Enregistrez MainWindow.xaml.

    Si vous avez un appareil qui prend en charge un stylet numérique (par exemple, une Surface) et que vous effectuez ces étapes sur un ordinateur physique, vous pouvez maintenant générer et exécuter l’application, et dessiner avec de l’encre numérique sur l’écran au moyen du stylet. Si vous essayez d’écrire avec la souris, rien ne se passe, car le contrôle InkCanvas est par défaut activé uniquement pour les stylets numériques. Voici comment activer InkCanvas pour la souris.

  5. Toujours dans MyWPFApp, ouvrez MainWindow.xaml.cs.

  6. Ajoutez la directive d’espace de noms suivante au début du fichier :

    using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT;
    
  7. Recherchez le constructeur MainWindow. Juste après l’appel à InitializeComponent, ajoutez la ligne de code suivante :

    myInkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Pen;
    

    Vous pouvez utiliser l’objet InkPresenter pour personnaliser l’expérience d’entrée manuscrite par défaut. Le code ci-dessus utilise la propriété InputDeviceTypes pour permettre l’entrée avec la souris comme avec le stylet.

  8. Enregistrez, générez et exécutez le code. Si vous utilisez un ordinateur avec une souris, vérifiez que vous pouvez utiliser celle-ci pour dessiner dans l’espace du canevas d’encre.

Héberger un CalendarView à l’aide du contrôle hôte

Dans cette section, nous allons utiliser le contrôle WindowsXamlHost pour ajouter un contrôle CalendarView à l’application.

Note

Le contrôle WindowsXamlHost est fourni par le package Microsoft.Toolkit.Wpf.UI.XamlHost. Ce package est inclus dans le package Microsoft.Toolkit.Wpf.UI.Controls que vous avez précédemment installé.

  1. Dans l’Explorateur de solutions, dans MyWPFApp, ouvrez le fichier MainWindow.xaml.

  2. Dans l’élément Window vers le début du fichier XAML, ajoutez l’attribut suivant. Cet attribut référence l’espace de noms XAML pour le contrôle WindowsXamlHost et le mappe à l’espace de noms XML xamlhost.

    xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
    
  3. Toujours dans MainWindow.xaml, modifiez l’élément Grid existant selon le code XAML ci-dessous. Ce code XAML ajoute à l’élément Grid un contrôle WindowsXamlHost (préfixé par l’espace de noms XML xamlhost que vous avez défini à l’étape précédente). Pour héberger un contrôle CalendarView UWP, ce code XAML définit la propriété InitialTypeName sur le nom complet du contrôle. Le code XAML définit également un gestionnaire d’événements pour l’événement ChildChanged, qui est déclenché une fois le contrôle hébergé affiché.

    <Grid Margin="10,50,10,10">
        <xamlhost:WindowsXamlHost x:Name="myCalendar" InitialTypeName="Windows.UI.Xaml.Controls.CalendarView"
              Margin="10,10,10,10" Width="600" Height="300" ChildChanged="MyCalendar_ChildChanged" />
    </Grid>
    
  4. Enregistrez MainWindow.xaml et ouvrez MainWindow.xaml.cs.

  5. Supprimez cette ligne de code, que nous avions ajoutée dans la section précédente : myInkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Pen;.

  6. Ajoutez la directive d’espace de noms suivante au début du fichier :

    using Microsoft.Toolkit.Wpf.UI.XamlHost;
    
  7. Ajoutez la méthode de gestionnaire d’événements ChildChanged suivante à la classe MainWindow. Une fois le contrôle hôte affiché, ce gestionnaire d’événements s’exécute et crée un gestionnaire d’événements simple pour l’événement SelectedDatesChanged du contrôle calendrier.

    private void MyCalendar_ChildChanged(object sender, EventArgs e)
    {
        WindowsXamlHost windowsXamlHost = (WindowsXamlHost)sender;
    
        var calendarView =
            (Windows.UI.Xaml.Controls.CalendarView)windowsXamlHost.Child;
    
        if (calendarView != null)
        {
            calendarView.SelectedDatesChanged += (obj, args) =>
            {
                if (args.AddedDates.Count > 0)
                {
                    MessageBox.Show("The user selected a new date: " +
                        args.AddedDates[0].DateTime.ToString());
                }
            };
        }
    }
    
  8. Enregistrez, générez et exécutez le code. Vérifiez que le contrôle calendrier figure dans la fenêtre et qu’une zone de message s’affiche lorsque vous sélectionnez une date.

Empaqueter l’application

Vous avez l’option d’inclure votre application WPF dans un package MSIX en vue de son déploiement. MSIX est la technologie de création de packages d’applications moderne et fiable pour Windows.

Les instructions suivantes montrent comment inclure tous les composants de la solution dans un package MSIX en utilisant le projet de création de packages d’applications Windows dans Visual Studio (consultez Configurer votre application de bureau pour l’empaquetage MSIX dans Visual Studio). Ces étapes sont nécessaires uniquement si vous souhaitez empaqueter l’application WPF dans un package MSIX.

Note

Si vous choisissez de ne pas inclure votre application dans un package MSIX pour la déployer, Visual C++ Runtime doit être installé sur les ordinateurs qui exécuteront votre application.

  1. Ajoutez un nouveau projet à votre solution créée à partir du modèle Projet de création de packages d’applications Windows. Lorsque vous créez le projet, sélectionnez les mêmes version cible et version minimale que celles que vous avez sélectionnées pour le projet UWP.

  2. Dans le projet de création de packages, cliquez avec le bouton droit sur le nœud Dépendances, puis choisissez Ajouter une référence de projet.... Dans la liste des projets, sélectionnez MyWPFApp, puis cliquez sur OK.

    Note

    Si vous voulez publier votre application dans le Microsoft Store, vous devez aussi ajouter une référence au projet UWP dans le projet de création de packages.

  3. Si vous avez effectué les étapes jusqu’ici, tous les projets dans votre solution cibleront la même plateforme spécifique (x86 ou x64). Cela est nécessaire pour pouvoir générer l’application WPF dans un package MSIX à l’aide du projet de création de packages d’applications Windows. Pour vérifier ce point, effectuez ces étapes :

    1. Cliquez avec le bouton droit sur le nœud de la solution (pas sur le nœud du projet) dans l’Explorateur de solutions, puis choisissez Propriétés.
    2. Sélectionnez Propriétés de configuration sur la gauche.
    3. Cliquez sur le bouton Configuration Manager....
    4. Vérifiez que tous les projets listés ont la même valeur sous Plateforme : x86 ou x64.
  4. Cliquez avec le bouton droit sur le nœud du projet de création de packages que vous venez d’ajouter, puis cliquez sur Définir en tant que projet de démarrage.

  5. Générez et exécutez le projet d’empaquetage. Vérifiez que l’application WPF s’exécute correctement et que chaque contrôle UWP s’affiche comme prévu.

  6. Pour plus d’informations sur la distribution/le déploiement du package, consultez Gérer votre déploiement MSIX.