Verwenden von XAML Islands zum Hosten eines UWP-XAML-Steuerelements in einer C#-WPF-App

Wichtig

In diesem Thema werden Typen aus dem GitHub-Repository CommunityToolkit/Microsoft.Toolkit.Win32 verwendet oder erwähnt. Wichtige Informationen zur Unterstützung von XAML Islands finden Sie in diesem Repository im Hinweis zu XAML Islands.

In diesem Thema wird gezeigt, wie Sie eine C#-WPF-App (Windows Presentation Foundation) (für .NET Core 3.1) erstellen, die XAML Islands verwendet, um ein UWP-XAML-Steuerelement (Universal Windows Platform) (d. h. ein vom Windows SDK bereitgestelltes Erstanbieter-Steuerelement) zu hosten. Wir zeigen zwei Arten, wie Sie dies erreichen können:

  • Wir zeigen, wie Sie die UWP-Steuerelemente InkCanvas und InkToolbar unter Verwendung von umschlossenen Steuerelementen (verfügbar im Windows-Community-Toolkit) hosten. Umschlossene Steuerelemente kapseln Schnittstelle und Funktionalität einer kleinen Teilmenge nützlicher UWP-XAML-Steuerelemente. Sie können umschlossene Steuerelemente direkt der Entwurfsoberfläche Ihres WPF- oder Windows Forms-Projekts hinzufügen und sie dann wie jedes andere WPF- oder Windows Forms-Steuerelement im Designer verwenden.

  • Außerdem wird gezeigt, wie Sie ein UWP-Steuerelement CalendarView unter Verwendung des Steuerelements WindowsXamlHost (verfügbar im Windows-Community-Toolkit) hosten. Da nur eine kleine Teilmenge der UWP-XAML-Steuerelemente in Form von umschlossenen Steuerelementen verfügbar ist, können Sie WindowsXamlHost verwenden, um beliebige UWP-XAML-Steuerelemente zu hosten.

Der Prozess zum Hosten eines UWP-XAML-Steuerelements in einer WPF-App ist für eine Windows Forms-App ähnlich.

Wichtig

Die Verwendung von XAML Islands (umschlossene Steuerelemente oder WindowsXamlHost) zum Hosten von UWP-XAML-Steuerelementen wird nur in Apps unterstützt, die auf .NET Core 3.x ausgerichtet sind. XAML Islands werden in Apps für die Zielplattform .NET oder in Apps, die auf eine beliebige Version von .NET Frameworks abzielen, nicht unterstützt.

Um ein UWP-XAML-Steuerelement in einer WPF- oder Windows Forms-App zu hosten, empfehlen wir Ihnen, die folgenden Komponenten in der Projektmappe zu verwenden. In diesem Thema werden Anweisungen zum Erstellen jeder dieser Komponenten bereitgestellt:

  • Das Projekt und der Quellcode für Ihre WPF- oder Windows Forms-App.

  • UWP-Projekt mit Definition einer Stammanwendungsklasse, die von XamlApplication abgeleitet ist. Die Klasse Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication ist im Windows-Community-Toolkit verfügbar). Wir empfehlen Ihnen, Ihre von XamlApplication abgeleitete Application-Klasse als separates UWP-App-Projekt zu definieren, das Teil Ihrer WPF- oder Windows Forms-Visual Studio-Projektmappe ist.

    Hinweis

    Es ist eigentlich nicht erforderlich, ein von XamlApplication abgeleitetes Objekt für Ihr WPF- oder Windows Forms-Projekt verfügbar zu machen, um ein UWP-XAML-Steuerelement von Erstanbietern zu hosten. Zum Ermitteln, Laden und Hosten benutzerdefinierter UWP-XAML-Steuerelemente ist es allerdings erforderlich. Zur Unterstützung sämtlicher XAML Island-Szenarien empfehlen wir Ihnen daher, in jeder Projektmappe, in der Sie XAML Island verwenden, immer ein von XamlApplication abgeleitetes Objekt zu definieren.

    Hinweis

    Ihre Projektmappe kann nur ein Projekt enthalten, das ein von XamlApplication abgeleitetes Objekt definiert. Dieses eine Projekt muss auf alle anderen Bibliotheken und Projekte verweisen, die UWP-XAML-Steuerelemente über XAML Islands hosten.

Erstellen eines WPF-Projekts

Befolgen Sie diese Anweisungen, um ein neues WPF-Projekt zu erstellen und es zum Hosting in XAML Islands zu konfigurieren. Wenn Sie über ein vorhandenes WPF-Projekt verfügen, können Sie diese Schritte und Codebeispiele für Ihr Projekt anpassen.

  1. Wenn noch nicht geschehen, installieren Sie die neueste Version von .NET Core 3.1.

  2. Erstellen Sie in Visual Studio ein neues C#-Projekt unter Verwendung der Projektvorlage WPF-Anwendung. Legen Sie den Project Namen auf MyWPFApp fest, damit Sie die Schritte oder den Quellcode in diesem Thema nicht bearbeiten müssen. Legen Sie Framework auf .NET Core 3.1* fest, und klicken Sie auf Erstellen.

Wichtig

Achten Sie darauf, nicht die Projektvorlage WPF-App (.NET Framework) zu verwenden.

Konfigurieren Ihres WPF-Projekts

  1. Mit diesen Schritten werden Paketverweise aktiviert:

    1. Klicken Sie in Visual Studio auf Extras>NuGet-Paket-Manager >Paket-Manager-Einstellungen.
    2. Suchen Sie auf der rechten Seite die Einstellung Paketverwaltung>Standardformat für Paketverwaltung, und legen Sie sie auf PackageReference fest.
  2. Verwenden Sie diese Schritte, um das NuGet-Paket Microsoft.Toolkit.Wpf.UI.Controls zu installieren:

    1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektknoten MyWPFApp, und wählen Sie NuGet-Pakete verwalten aus.

    2. Geben oder fügen Sie auf der Registerkarte Durchsuchen die Zeichenfolge Microsoft.Toolkit.Wpf.UI.Controls in das Suchfeld ein. Wählen Sie die neueste stabile Version aus, und klicken Sie auf Installieren. Das Paket enthält alle benötigten Elemente zur Verwendung der umschlossenen UWP-XAML-Steuerelemente für WPF (einschließlich der Steuerelemente InkCanvas, InkToolbar und WindowsXamlHost).

    Hinweis

    Verweisen Sie für eine Windows Forms-App stattdessen auf das Paket Microsoft.Toolkit.Forms.UI.Controls.

  3. Die meisten XAML Islands-Szenarien werden für Projekte, die als Ziel Beliebige CPU verwenden, nicht unterstützt. Gehen Sie daher wie folgt vor, um eine bestimmte Architektur (z. B. x86 oder x64) als Ziel zu verwenden:

    1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektmappenknoten (nicht den Projektknoten), und wählen Sie Eigenschaften aus.
    2. Wählen Sie auf der linken Seite Konfigurationseigenschaften aus.
    3. Klicken Sie auf die Schaltfläche Konfigurations-Manager.
    4. Klicken Sie unter Aktive Projektmappenplattform auf Neu.
    5. Wählen Sie im Dialogfeld Neue Projektmappenplattform die Option x64 oder x86 aus, und klicken Sie auf OK.
    6. Schließe die geöffneten Dialogfelder.

Definieren einer XamlApplication-Klasse in einem neuen UWP-Projekt

In diesem Abschnitt fügen Sie der Projektmappe ein UWP-Projekt hinzu und überarbeiten die Standardklasse App in diesem Projekt, um sie von der im Windows-Community-Toolkit bereitgestellten Klasse Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication abzuleiten. Diese Klasse unterstützt die IXamlMetadataProvider-Schnittstelle, mit der Ihre App Metadaten für benutzerdefinierte UWP-XAML-Steuerelemente in Assemblys im aktuellen Verzeichnis der Anwendung zur Laufzeit ermitteln und laden kann. Diese Klasse initialisiert außerdem das UWP-XAML-Framework für den aktuellen Thread.

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektmappenknoten, und wählen Sie Hinzufügen>Neues Projekt aus.

  2. Wählen Sie die C#-Projektvorlage Leere App (universelles Windows) aus. Legen Sie den Project Namen auf MyUWPApp fest, damit Sie die Schritte oder den Quellcode in diesem Thema nicht bearbeiten müssen. Legen Sie Zielversion und Mindestversion entweder auf Windows 10, Version 1903 (Build 18362) oder höher fest.

    Hinweis

    Achten Sie darauf, myUWPApp nicht in einem Unterordner von MyWPFApp zu erstellen. Andernfalls versucht MyWPFApp, das UWP-XAML-Markup so zu erstellen, als wäre es WPF-XAML.

  3. Installieren Sie in MyUWPApp das NuGet-Paket Microsoft.Toolkit.Win32.UI.XamlApplication (neueste stabile Version). Das Verfahren zum Installieren eines NuGet-Pakets wurde im vorherigen Abschnitt beschrieben.

  4. Öffnen Sie in MyUWPApp die Datei App.xaml, und ersetzen Sie ihren Inhalt durch den folgenden XAML-Code:

    <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. Öffnen Sie außerdem App.xaml.cs, und ersetzen Sie den Inhalt durch den folgenden Code:

    namespace MyUWPApp
    {
        public sealed partial class App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
        {
            public App()
            {
                this.Initialize();
            }
        }
    }
    
  6. Löschen Sie die Dateien MainPage.xaml und MainPage.xaml.cs.

  7. Erstellen Sie das Projekt MyUWPApp.

Fügen Sie in MyWPFApp einen Verweis auf das MyUWPApp-Projekt hinzu.

  1. Geben Sie die kompatible Frameworkversion in der MyWPFApp-Projektdatei wie folgt an:

    1. Klicken Sie im Projektmappen-Explorer auf den Projektknoten MyWPFApp, um die Projektdatei im Editor zu öffnen.

    2. Fügen Sie im ersten PropertyGroup-Element das folgende untergeordnete Element hinzu. Ändern Sie den 19041-Teil des Werts nach Bedarf auf die Werte des Ziel- und Mindestbetriebssystembuilds des MyWPFApp-Projekts.

      <AssetTargetFallback>uap10.0.19041</AssetTargetFallback>
      
  2. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf MyWPFApp>Abhängigkeiten, wählen Sie Projektverweis hinzufügen aus, und fügen Sie einen Verweis auf das Projekt MyUWPApp hinzu.

Instanziieren des XamlApplication-Objekts im Einstiegspunkt von MyWPFApp

Fügen Sie als Nächstes Code zum Einstiegspunkt von MyWPFApp hinzu, um eine Instanz der App-Klasse zu erstellen, die Sie soeben in MyUWPApp definiert haben (die von XamlApplication abgeleitete Klasse).

  1. Klicken Sie mit der rechten Maustaste auf den Projektknoten MyWPFApp, wählen Sie Hinzufügen>Neues Element und dann Klasse aus. Legen Sie Name auf Program.cs fest, und klicken Sie auf Hinzufügen.

  2. Ersetzen Sie den Inhalt von Program.cs durch den folgenden XAML-Code (speichern Sie die Datei dann, und erstellen Sie das Projekt 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. Klicken Sie mit der rechten Maustaste auf den Projektknoten MyWPFApp, und wählen Sie Eigenschaften aus.

  4. Klicken Sie in Anwendung>Allgemein auf die Dropdownliste Startobjekt, und wählen Sie MyWPFApp.Program aus (vollqualifizierter Name der soeben hinzugefügten Program-Klasse). Wenn es nicht angezeigt wird, versuchen Sie, Visual Studio zu schließen und erneut zu öffnen.

    Hinweis

    Standardmäßig definiert ein WPF-Projekt eine Main-Einstiegspunktfunktion in einer generierten Codedatei, die nicht zur Bearbeitung vorgesehen ist. Durch den oben stehenden Schritt wird der Einstiegspunkt für Ihr Projekt in die Main-Methode der neuen Program-Klasse geändert, wodurch Sie Code hinzufügen können, der so früh wie möglich in der Startphase der App ausgeführt wird.

  5. Speichere deine Änderungen an den Projekteigenschaften.

Verwenden umschlossener Steuerelemente zum Hosten von InkCanvas und InkToolbar

Nachdem Sie Ihr Projekt zur Verwendung von UWP XAML Islands konfiguriert haben, können Sie jetzt die umschlossenen UWP-XAML-Steuerelemente InkCanvas und InkToolbar zur App hinzufügen.

  1. Öffnen Sie die Datei MainWindow.xaml in MyWPFApp.

  2. Füge dem Window-Element im oberen Bereich der XAML-Datei das folgende Attribut hinzu. Dieses Attribut verweist auf den XAML-Namespace für die umschlossenen UWP-XAML-Steuerelemente InkCanvas und InkToolbar und ordnet ihn dem controls-XML-Namespace zu.

    xmlns:controls="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls"
    
  3. Bearbeiten Sie in MainWindow.xaml das vorhandene Raster so, dass es wie im folgenden XAML-Code aussieht. Dieser XAML-Code fügt dem Raster ein InkCanvas- und ein InkToolbar-Steuerelement hinzu (mit dem im vorherigen Schritt definierten controls-XML-Namespace als Präfix).

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

    Hinweis

    Sie können diese und weitere umschlossene Steuerelemente zum Fenster hinzufügen, indem Sie vom Abschnitt Windows-Community-Toolkit der Toolbox in den Designer ziehen.

  4. Speichern Sie MainWindow.xaml.

    Wenn Sie über ein Gerät verfügen, das einen digitalen Stift unterstützt (wie beispielsweise Surface), und Sie die Übung auf einem physischen Computer ausführen, können Sie jetzt die App erstellen und ausführen und mit dem Stift Freihandeingaben auf dem Bildschirm zeichnen. Wenn Sie jedoch versuchen, mit der Maus zu schreiben, geschieht nichts, da InkCanvas standardmäßig nur für digitale Stifte aktiviert ist. So aktivieren Sie InkCanvas für die Maus.

  5. Öffnen Sie MainWindow.xaml.cs in MyWPFApp.

  6. Fügen Sie am Anfang der Datei die folgende Namespacedirektive hinzu:

    using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT;
    
  7. Suchen Sie den Konstruktor MainWindow. Fügen Sie unmittelbar nach dem Aufruf von InitializeComponent die folgende Codezeile hinzu:

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

    Du kannst das Standardverhalten für die Freihandeingabe mit dem InkPresenter-Objekt anpassen. Der oben stehende Code verwendet die InputDeviceTypes-Eigenschaft, um sowohl die Maus- als auch die Stifteingabe zu aktivieren.

  8. Speichern, Erstellen und Ausführen. Wenn Sie einen Computer mit Maus verwendest, vergewissern Sie sich, dass Sie im Zeichenbereich mit der Maus zeichnen können.

Hosten einer CalendarView durch Verwendung des Hoststeuerelements

In diesem Abschnitt verwenden wir das WindowsXamlHost-Steuerelement, um der App ein CalendarView-Objekt hinzuzufügen.

Hinweis

Das Steuerelement WindowsXamlHost wird vom Paket Microsoft.Toolkit.Wpf.UI.XamlHost bereitgestellt. Dieses Paket ist im Microsoft.Toolkit.Wpf.UI.Controls-Paket enthalten, das Sie in einem vorherigen Schritt installiert haben.

  1. Öffnen Sie im Projektmappen-Explorer in MyWPFApp die Datei MainWindow.xaml.

  2. Füge dem Window-Element im oberen Bereich der XAML-Datei das folgende Attribut hinzu. Dieses Attribut verweist auf den XAML-Namespace für das Steuerelement WindowsXamlHost und ordnet es dem XML-Namespace xamlhost zu.

    xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
    
  3. Bearbeiten Sie in MainWindow.xaml das vorhandene Raster so, dass es wie im folgenden XAML-Code aussieht. Dieser XAML-Code fügt dem Raster ein WindowsXamlHost-Steuerelement hinzu (mit dem im vorherigen Schritt definierten xamlhost-XML-Namespace als Präfix). Zum Hosten eines UWP-Steuerelements CalendarView legt dieser XAML-Code die Eigenschaft InitialTypeName auf den vollqualifizierten Namen des Steuerelements fest. Darüber hinaus wird ein Ereignishandler für das Ereignis ChildChanged definiert, das ausgelöst wird, wenn das gehostete Steuerelement gerendert wurde.

    <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. Speichern Sie MainWindow.xaml, und öffnen Sie MainWindow.xaml.cs.

  5. Löschen Sie diese Codezeile, die wir im vorherigen Abschnitt hinzugefügt haben: myInkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Pen;.

  6. Fügen Sie am Anfang der Datei die folgende Namespacedirektive hinzu:

    using Microsoft.Toolkit.Wpf.UI.XamlHost;
    
  7. Fügen Sie die folgende ChildChanged-Ereignishandlermethode zur MainWindow-Klasse hinzu. Wenn das Hoststeuerelement gerendert wurde, wird dieser Ereignishandler ausgeführt und erstellt einen einfachen Ereignishandler für das SelectedDatesChanged-Ereignis des Kalendersteuerelements.

    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. Speichern, Erstellen und Ausführen. Vergewissern Sie sich, dass das Kalendersteuerelement im Fenster angezeigt wird und dass ein Meldungsfeld erscheint, wenn Sie ein Datum auswählen.

Packen der App

Sie können Ihre WPF-App optional in einem MSIX-Paket für die Bereitstellung packen. MSIX ist die moderne und zuverlässige App-Paketerstellungstechnologie für Windows.

Die folgenden Anweisungen zeigen, wie Sie alle Komponenten der Projektmappe mithilfe von Paketerstellungsprojekt für Windows-Anwendungen in Visual Studio in ein MSIX-Paket packen (siehe Einrichten Ihrer Desktopanwendung für die MSIX-Paketerstellung in Visual Studio). Diese Schritte sind nur erforderlich, wenn du die WPF-App in einem MSIX-Paket packen möchtest.

Hinweis

Wenn Sie sich entscheiden, Ihre Anwendung nicht für die Bereitstellung in einem MSIX-Paket zu packen, muss auf Computern zur Ausführung Ihrer App die Visual C++-Runtime installiert sein.

  1. Fügen Sie der aus der Projektvorlage Paketerstellungsprojekt für Windows-Anwendungen erstellten Projektmappe ein neues Projekt hinzu. Wählen Sie beim Erstellen des Projekts dieselbe Zielversion und Mindestversion aus, wie Sie sie für das UWP-Projekt ausgewählt haben.

  2. Klicken Sie im Paketerstellungsprojekt mit der rechten Maustaste auf den Knoten Abhängigkeiten, und wählen Sie Projektverweis hinzufügen aus. Wählen Sie in der Liste der Projekte MyWPFApp aus, und klicken Sie auf OK.

    Hinweis

    Wenn Sie Ihre App im Microsoft Store veröffentlichen möchten, müssen Sie auch im Paketprojekt einen Verweis auf das UWP-Projekt hinzufügen.

  3. Wenn Sie die Schritte bis zu diesem Punkt befolgt haben, sind alle Projekte in Ihrer Projektmappe auf dieselbe spezifische Plattform ausgerichtet (x86 oder x64). Dies ist erforderlich, um die WPF-App über „Paketerstellungsprojekt für Windows-Anwendungen“ in einem MSIX-Paket zu packen. Um das zu bestätigen, können Sie diese Schritte ausführen:

    1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektmappenknoten (nicht den Projektknoten), und wählen Sie Eigenschaften aus.
    2. Wählen Sie auf der linken Seite Konfigurationseigenschaften aus.
    3. Klicken Sie auf die Schaltfläche Konfigurations-Manager.
    4. Vergewissern Sie sich, dass alle aufgelisteten Projekte unter Plattform den gleichen Wert aufweisen: x86 oder x64.
  4. Klicken Sie mit der rechten Maustaste auf den Projektknoten für das Paketerstellungsprojekt, das Sie gerade hinzugefügt haben, und klicken Sie auf Als Startprojekt festlegen.

  5. Kompiliere das Paketerstellungsprojekt, und führe es aus. Vergewissern Sie sich, dass die WPF-App ausgeführt wird und die UWP-Steuerelemente wie erwartet angezeigt werden.

  6. Informationen zum Verteilen/Bereitstellen des Pakets finden Sie unter Verwalten Ihrer MSIX-Bereitstellung.