Usare le isole XAML per ospitare un controllo XAML UWP in un'app WPF C#

Importante

Questo argomento usa o menziona tipi del repository GitHub CommunityToolkit/Microsoft.Toolkit.Win32. Per informazioni importanti sul supporto per le isole XAML, vedi l'avviso sulle isole XAML nel repository citato.

Questo argomento illustra come creare un'app Windows Presentation Foundation (WPF) C# (destinata a .NET Core 3.1) che usa le isole XAML per ospitare un controllo XAML della piattaforma UWP (Universal Windows Platform), ovvero un controllo di prima parte fornito da Windows SDK. Mostriamo come eseguire tale operazione in due modi:

  • Mostriamo come ospitare i controlli UWP InkCanvas e InkToolbar usando controlli incapsulati (disponibili nel Windows Community Toolkit). Questi controlli incapsulati eseguono il wrapping dell'interfaccia e delle funzionalità di un piccolo set di utili controlli XAML UWP. Puoi aggiungere un controllo incapsulato direttamente nell'area di progettazione del tuo progetto WPF o Windows Form e quindi usarli nella finestra di progettazione come qualsiasi altro controllo Windows Form o WPF.

  • Mostriamo inoltre come ospitare un controllo UWP CalendarView usando il controllo WindowsXamlHost (disponibile nel Windows Community Toolkit). Poiché come controlli incapsulati è disponibile solo un set limitato di controlli UWP XAML, per ospitare qualsiasi altro controllo UWP XAML puoi usare WindowsXamlHost.

Il processo per l'hosting di un controllo XAML UWP in un'app WPF è simile a quello che si usa per un'app Windows Form.

Importante

L'uso di isole XAML (controlli incapsulati o WindowsXamlHost) per ospitare i controlli XAML UWP è supportato solo nelle app destinate a .NET Core 3.x. Le isole XAML non sono supportate nelle app destinate a .NET o in quelle destinate a qualsiasi versione di .NET Framework.

Per ospitare un controllo XAML UWP in un'app WPF o Windows Form, ti consigliamo di disporre dei componenti seguenti nella soluzione. In questo argomento vengono fornite le istruzioni per creare ciascuno di questi componenti:

  • Il progetto e il codice sorgente per l'app WPF o Windows Form.

  • Un progetto UWP che definisce una classe Application radice derivata da XamlApplication. La classe Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication è disponibile nel Windows Community Toolkit. È consigliabile definire la classe Applicationderivata da XamlApplication in un progetto di app UWP separato che fa parte della soluzione WPF o Windows Forms di Visual Studio.

    Nota

    Per ospitare un controllo XAML UWP di prima parte non è effettivamente necessario rendere disponibile un oggetto derivato da XamlApplication per il progetto WPF o Windows Form. Ma è necessario per individuare, caricare e ospitare controlli XAML UWP personalizzati. Quindi, per supportare l'intera gamma di scenari dell'isola XAML, ti consigliamo di definire sempre un oggetto derivato da XamlApplication in qualsiasi soluzione in cui usi le isole XAML.

    Nota

    La soluzione può contenere un solo progetto che definisce un oggetto derivato da XamlApplication. Tale progetto deve fare riferimento a eventuali altre librerie e progetti che ospitano controlli XAML UWP tramite isole XAML.

Creare un progetto WPF

Puoi seguire queste istruzioni per creare un nuovo progetto WPF e configurarlo in modo da ospitare le isole XAML. Se disponi di un progetto WPF esistente, puoi adattare questi passaggi ed esempi di codice per il tuo progetto.

  1. Se non lo hai già fatto, installa la versione più recente di .NET Core 3.1.

  2. Crea un nuovo progetto C# in Visual Studio dal modello di progetto WPF Application. Imposta il Nome del progetto su MyWPFApp in modo che non sia necessario modificare i passaggi o il codice sorgente in questo argomento. Imposta Framework su .NET Core 3.1* e fai clic su Crea.

Importante

Assicurati di non usare il modello di progetto App WPF (.NET Framework).

Configurare il progetto WPF

  1. Questi passaggi abilitano i riferimenti ai pacchetti:

    1. In Visual Studio fai clic su Strumenti>Gestione pacchetti NuGet>Impostazioni di Gestione pacchetti.
    2. A destra, individua l'impostazione Gestione pacchetti> Formato gestione di pacchetti predefinito e impostalo su PackageReference.
  2. Usa questi passaggi per installare il pacchetto NuGet Microsoft.Toolkit.Wpf.UI.Controls:

    1. Fai clic con il pulsante destro del mouse sul progetto MyWPFApp in Esplora soluzioni e scegli Gestisci pacchetti NuGet.

    2. Nella scheda Sfoglia, digita o incolla Microsoft.Toolkit.Wpf.UI.Controls nella casella di ricerca. Seleziona la versione stabile più recente e fai clic su Installa. Questo pacchetto offre tutto ciò che è necessario per usare i controlli UWP XAML incapsulati per WPF, inclusi InkCanvas, InkToolbar e WindowsXamlHost.

    Nota

    Invece, per un'app Windows Form fai riferimento al pacchetto Microsoft.Toolkit.Forms.UI.Controls.

  3. La maggior parte degli scenari di isole XAML non è supportata nei progetti destinati a Qualsiasi CPU. Per specificare come destinazione un'architettura specifica, ad esempio x86 o x64, esegui le operazioni riportate qui:

    1. Fai clic con il pulsante destro del mouse sul nodo della soluzione (non sul nodo del progetto) in Esplora soluzioni e scegli Proprietà.
    2. A sinistra, seleziona Proprietà di configurazione.
    3. Fai clic sul pulsante Gestione configurazione.
    4. In Piattaforma soluzione attiva seleziona Nuovo.
    5. Nella finestra di dialogo Nuova piattaforma soluzione seleziona x64 o x86 e premi OK.
    6. Chiudi le finestre di dialogo aperte.

Definire una classe XamlApplication in un nuovo progetto UWP

In questa sezione verrà aggiunto un progetto UWP alla soluzione e verrà aggiornata la classe App predefinita in questo progetto in modo che derivi dalla classe Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication fornita da Windows Community Toolkit. Questa classe supporta l'interfaccia IXamlMetadataProvider, che consente all'app di individuare e caricare i metadati dei controlli XAML UWP personalizzati negli assembly nella directory corrente dall'applicazione in fase di esecuzione. La classe inizializza anche il framework XAML UWP per il thread corrente.

  1. In Esplora soluzioni fai clic con il pulsante destro del mouse sul nodo della soluzione e scegli Aggiungi>Nuovo progetto.

  2. Seleziona il modello di progetto App vuota C# (Windows universale). Imposta il Nome del progetto su MyWPFApp in modo che non sia necessario modificare i passaggi o il codice sorgente in questo argomento. Imposta la versione di destinazione e la versione minima su Windows 10, versione 1903 (Build 18362) o successiva.

    Nota

    Assicurati di non creare MyUWPApp in una sottocartella di MyWPFApp. In questo caso, MyWPFApp tenterà di compilare il markup UWP XAML come se si trattasse di XAML WPF.

  3. In MyUWPApp, installa il pacchetto NuGet Microsoft.Toolkit.Win32.UI.XamlApplication (versione stabile più recente). Il processo di installazione di un pacchetto NuGet è stato descritto nella sezione precedente.

  4. In MyUWPApp, apri il file App.xaml e sostituiscine il contenuto con il seguente XAML:

    <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. Analogamente, apri App.xaml.cs e sostituisci il contenuto con il codice seguente:

    namespace MyUWPApp
    {
        public sealed partial class App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
        {
            public App()
            {
                this.Initialize();
            }
        }
    }
    
  6. Elimina i file MainPage.xaml e MainPage.xaml.cs.

  7. Compila il progetto MyUWPApp.

In MyWPFApp, aggiungi un riferimento al progetto MyUWPApp

  1. Specifica la versione del framework compatibile nel file di progetto di MyWPFAppcome segue:

    1. In Esplora soluzioni, fai clic sul nodo del progetto MyWPFApp per aprire il file di progetto nell'editor.

    2. All’interno del primo elemento PropertyGroup aggiungi l'elemento figlio seguente. Modificare la parte 19041 del valore in modo che corrisponda alla build del sistema operativo minima e di destinazione del progetto MyWPFApp.

      <AssetTargetFallback>uap10.0.19041</AssetTargetFallback>
      
  2. In Esplora soluzioni, fai clic con il pulsante destro del mouse su Dipendenze> di MyWPFApp, scegli Aggiungi riferimento progetto e aggiungi un riferimento al progetto MyUWPApp.

Creare un'istanza dell'oggetto XamlApplication nel punto di ingresso di MyWPFApp

A questo punto, aggiungi il codice al punto di ingresso di MyWPFApp per creare un'istanza della classe App appena definita in MyUWPApp (la classe che deriva da XamlApplication).

  1. Fai clic con il pulsante destro del mouse sul nodo del progetto MyWPFApp, scegli Aggiungi>Nuovo elemento e poi seleziona Classe. Imposta Nome su Program.cse fai clic su Aggiungi.

  2. Sostituisci il contenuto di Program.cs con il codice XAML seguente (dopodiché, salva il file e compila il progetto 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. Fai clic con il pulsante destro del mouse sul nodo del progetto MyWPFApp e scegli Proprietà.

  4. In Applicazione>Generale, fai clic sul menu a discesa Oggetto di avvio e scegli MyWPFApp.Program, ovvero il nome completo della classe Programma appena aggiunta. Se non viene visualizzato, prova a chiudere e riaprire Visual Studio.

    Nota

    Per impostazione predefinita, un progetto WPF definisce una funzione Principale del punto di ingresso in un file di codice generato che non deve essere modificato. Con il passaggio su riportato, il punto di ingresso del progetto viene modificato nel metodo Principale della nuova classe Programma. Ciò consente di aggiungere codice che viene eseguito il prima possibile nel processo di avvio dell'app.

  5. Salva le modifiche apportate alle proprietà del progetto.

Usare i controlli incapsulati per ospitare InkCanvas e InkToolbar

Ora che hai configurato il progetto per l'uso delle isole XAML UWP, puoi aggiungere all'app i controlli UWP XAML incapsulati InkCanvas e InkToolbar.

  1. In MyWPFApp, apri il file MainWindow.xaml.

  2. Nell'elemento Window accanto alla parte superiore del file XAML aggiungi l'attributo seguente, Questo attributo fa riferimento allo spazio dei nomi XAML per i controlli XAML incapsulati InkCanvas e InkToolbar ed esegue il mapping ai controlli spazio dei nomi XML.

    xmlns:controls="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls"
    
  3. Sempre in MainWindow.xaml, modifica l'elemento Griglia esistente in modo che abbia un aspetto simile al codice XAML seguente. Questo codice XAML aggiunge alla Griglia un controllo InkCanvas e un controllo InkToolbar (preceduto dallo spazio dei nomi XML dei controlli che hai definito nel passaggio precedente).

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

    Nota

    Puoi anche aggiungere alla finestra questi e altri controlli incapsulati trascinandoli nella finestra di progettazione dalla sezione Windows Community Toolkit della casella degli strumenti.

  4. Salvare MainWindow.xaml.

    Se hai un dispositivo che supporta una penna digitale, come un dispositivo Surface, ed esegui l’operazione su un computer fisico, ora puoi compilare ed eseguire l'app e tracciare l'input penna digitale sullo schermo usando la penna. Ma se tenti di scrivere con il mouse, non succederà nulla, perché per impostazione predefinita InkCanvas è abilitato solo per penne digitali. Ecco come abilitare InkCanvas per il mouse.

  5. Sempre in MyWPFApp, apri MainWindow.xaml.cs.

  6. Aggiungi la direttiva dello spazio dei nomi seguente all'inizio del file:

    using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT;
    
  7. Individua il costruttore MainWindow. Subito dopo la chiamata a InitializeComponent, aggiungi la seguente riga di codice:

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

    Puoi usare l'oggetto InkPresenter per personalizzare l'esperienza di input penna predefinita. Il codice su riportato usa la proprietà InputDeviceTypes per abilitare il mouse e l'input penna.

  8. Salva, compila ed esegui. Se usi un computer con il mouse, verifica che sia possibile tracciare qualcosa nell'area di disegno dell'input penna con il mouse.

Ospitare un controllo CalendarView usando il controllo host

In questa sezione si userà il controllo WindowsXamlHost per aggiungere un elemento CalendarView all'app.

Nota

Il controllo WindowsXamlHost viene fornito dal pacchetto Microsoft.Toolkit.Wpf.UI.XamlHost, Tale pacchetto è incluso nel pacchetto Microsoft.Toolkit.Wpf.UI.Controls installato in precedenza.

  1. In Esplora soluzioni, apri il file in MyWPFAppMainWindow.xaml.

  2. Nell'elemento Window accanto alla parte superiore del file XAML aggiungi l'attributo seguente, Tale attributo fa riferimento allo spazio dei nomi XAML per il controllo WindowsXamlHost ed esegue il mapping allo spazio dei nomi XML xamlhost.

    xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
    
  3. Sempre in MainWindow.xaml, modifica l'elemento Griglia esistente in modo che abbia un aspetto simile al codice XAML seguente. Questo codice XAML aggiunge alla Griglia un controllo WindowsXamlHost (preceduto dallo spazio dei nomi XML xamlhost definito nel passaggio precedente). Per ospitare un controllo UWP CalendarView, questo codice XAML imposta la proprietà InitialTypeName sul nome completo del controllo. Il codice XAML definisce anche un gestore eventi per l'evento ChildChanged, che viene generato quando viene eseguito il rendering del controllo ospitato.

    <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. Salva MainWindow.xaml e apri MainWindow.xaml.cs.

  5. Elimina questa riga di codice, aggiunta nella sezione precedente: myInkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Pen;.

  6. Aggiungi la seguente direttiva dello spazio dei nomi all'inizio del file:

    using Microsoft.Toolkit.Wpf.UI.XamlHost;
    
  7. Aggiungi il seguente metodo del gestore eventi ChildChangedalla classe MainWindow. Quando viene eseguito il rendering del controllo host, questo gestore eventi viene eseguito e crea un gestore eventi semplice per l'evento SelectedDatesChanged del controllo del calendario.

    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. Salva, compila ed esegui. Quando selezioni una data, verifica che il controllo calendario sia visualizzato nella finestra e che venga visualizzata una finestra di messaggio.

Creare un pacchetto per l'app

Facoltativamente, puoi creare per la tua app WPF un pacchetto MSIX da usare per la distribuzione. MSIX è la tecnologia di creazione di pacchetti di app moderna e affidabile per Windows.

Le istruzioni seguenti illustrano come creare un pacchetto di tutti i componenti della soluzione in un pacchetto MSIX usando il Progetto di creazione pacchetti per applicazioni Windows in Visual Studio (vedi Configurare l'applicazione desktop per la creazione di pacchetti MSIX in Visual Studio). Questi passaggi sono necessari solo se vuoi creare un pacchetto MSIX per l'app WPF.

Nota

Se scegli di non creare un pacchetto MSIX dell'applicazione per la distribuzione, nei computer che eseguono l'app deve essere installato il Visual C++ Runtime.

  1. Aggiungi un nuovo progetto alla soluzione creata dal modello di Progetto di creazione pacchetti per applicazioni Windows. Durante la creazione del progetto, per Versione di destinazione e Versione minima selezionare lo stesso valore scelto per il progetto UWP.

  2. Nel progetto di creazione del pacchetto, fai clic con il pulsante destro del mouse sul nodo Dipendenze e scegli Aggiungi riferimento al progetto. Nell'elenco dei progetti, seleziona MyWPFApp e fai clic su OK.

    Nota

    Se vuoi pubblicare la tua app in Microsoft Store, devi aggiungere anche un riferimento al progetto UWP nel progetto di creazione del pacchetto.

  3. Se sono stati seguiti i passaggi fino a questo punto, tutti i progetti nella soluzione saranno destinati alla stessa piattaforma specifica (x86 o x64). E tale operazione è necessaria per compilare l'app WPF in un pacchetto MSIX usando Progetto di creazione pacchetti per applicazioni Windows. Per confermare questa operazione, è possibile seguire questa procedura:

    1. Fai clic con il pulsante destro del mouse sul nodo della soluzione (non sul nodo del progetto) in Esplora soluzioni e scegli Proprietà.
    2. A sinistra, seleziona Proprietà di configurazione.
    3. Fai clic sul pulsante Gestione configurazione.
    4. Verifica che tutti i progetti elencati abbiano lo stesso valore in Piattaforma: x86 o x64.
  4. Fai clic con il pulsante destro del mouse sul nodo del progetto di creazione del pacchetto appena aggiunto e fai clic su Imposta come progetto di avvio.

  5. Compila ed esegui il progetto di creazione del pacchetto. Verifica che l'app WPF venga eseguita e che i controlli UWP siano visualizzati come previsto.

  6. Per informazioni sulla trasmissione/distribuzione del pacchetto, vedi Gestire la distribuzione del tuo MSIX.