使用 XAML Islands 在 C# WPF 應用程式中裝載 UWP XAML 控制項

重要

本主題使用或提及來自 CommunityToolkit/Microsoft.Toolkit.Win32 GitHub 存放庫的類型。 如需 XAML Islands 支援的重要資訊,請參閱該存放庫中 XAML Islands 注意事項

本主題說明如何建置 C# Windows Presentation Foundation (WPF) 應用程式 (以 .NET Core 3.1 為目標),其使用 XAML Islands 來裝載通用 Windows 平台 (UWP) XAML 控制項 (也就是 Windows SDK 所提供的第一方控制項)。 我們示範如何以兩種方式執行:

  • 我們示範如何使用包裝控制項 (可在 Windows 社群工具組中取得) 來裝載 UWP InkCanvasInkToolbar 控制項。 包裝的控制項會包裝一小組實用 UWP XAML 控制項的介面與功能。 您可以將包裝的控制項直接新增至 WPF 或 Windows Forms 專案的設計介面,然後在設計工具中使用它,就像任何其他 WPF 或 Windows Forms 控制項一樣。

  • 我們也示範如何使用 WindowsXamlHost 控制項來裝載 UWP CalendarView 控制項 (可在 Windows 社群工具組中取得)。 由於只有一組 UWP XAML 控制項可作為包裝控制項使用,因此您可以使用 WindowsXamlHost 來裝載任何 UWP XAML 控制項。

在 WPF 應用程式中裝載 UWP XAML 控制項的處理程序類似於 Windows Forms 應用程式。

重要

只有以 .NET Core 3.x 為目標的應用程式才支援使用 XAML Islands (包裝的控制項或 WindowsXamlHost) 裝載 UWP XAML 控制項。 以 .NET 為目標的應用程式或以任何 .NET Framework 版本為目標的應用程式不支援 XAML Islands。

若要在 WPF 或 Windows Forms 應用程式中裝載 UWP XAML 控制項,建議您在方案中要有下列元件。 本主題提供建立每個元件的指示:

  • WPF 或 Windows Forms 應用程式的專案和原始程式碼

  • UWP 專案可定義從 XamlApplication 衍生的根應用程式類別Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication 類別可在 Windows 社群工具組中取得。 建議您定義 XamlApplication 衍生應用程式類別,這是 WPF 或 Windows Forms Visual Studio 解決方案的個別 UWP 應用程式專案。

    注意

    若要裝載第一方 UWP XAML 控制項,將 XamlApplication衍生物件提供給 WPF 或 Windows Forms 專案,實際上並不需要。 但是為了探索、載入及裝載自訂 UWP XAML 控制項,這必要的。 因此為了支援 XAML Island 案例的完整範圍,我們建議您一律在您使用 XAML Islands 的任何解決方案中定義 XamlApplication 衍生物件。

    注意

    您的方案只能包含一個專案,定義 XamlApplication 衍生物件。 該專案必須透過 XAML Islands 參考裝載 UWP XAML 控制項的任何其他程式庫和專案。

建立 WPF 專案

您可以遵循這些指示來建立新的 WPF 專案,並將其設定為裝載 XAML Islands。 如果有現有的 WPF 專案,則可針對您的專案調整這些步驟和程式碼範例。

  1. 如果您尚未這麼做,請安裝最新版的 .NET Core 3.1

  2. 在 Visual Studio 中,從 WPF 應用程式專案範本建立新的 C# 專案。 將專案名稱設定為 MyWPFApp ,這樣您就不需要編輯本主題中的任何步驟或原始程式碼。 將 Framework 設定為 .NET Core 3.1*,然後按一下 [建立]。

重要

請務必不要使用 WPF 應用程式 (.NET Framework) 專案範本。

設定 WPF 專案

  1. 這些步驟會啟用套件參考

    1. 在 Visual Studio 中,按一下 [工具]>[NuGet 套件管理員]>[套件管理員設定]
    2. 在右側,尋找 [套件管理]>[預設套件管理格式] 設定,並將它設定為 PackageReference
  2. 使用下列步驟來安裝 Microsoft.Toolkit.Wpf.UI.Controls NuGet 套件:

    1. 以滑鼠右鍵按一下 [方案總管] 中的 [MyWPFApp] 專案節點,然後選擇 [管理 NuGet 套件]

    2. 在 [瀏覽] 索引標籤上,在搜尋方塊中輸入或貼上 Microsoft.Toolkit.Wpf.UI.Controls。 選取最新的穩定版本,然後按一下 [安裝]。 此套件會提供使用 WPF 適用的已包裝 UWP XAML 控制項所需的一切 (包括 InkCanvasInkToolbarWindowsXamlHost 控制項)。

    注意

    若是 Windows Forms 應用程式,請改為參考 Microsoft.Toolkit.Forms.UI.Controls 套件。

  3. 在以任何 CPU 為目標的專案中,不支援大部分的 XAML Islands 案例。 因此,若要以特定架構為目標 (例如 x86x64),請執行下列動作:

    1. [方案總管] 中,以滑鼠右鍵按一下方案節點 (專案節點),然後選擇 [屬性]
    2. 選取左側 [組態屬性]。
    3. 按一下 [組態管理員] 按鈕。
    4. 在 [使用中的方案平台] 中,選取 [新增]
    5. 在 [新增方案平台] 對話方塊中,選取 [x64] 或 [x86],然後按 [確定]。
    6. 關閉已開啟的對話方塊。

在新 UWP 專案中定義 XamlApplication 類別

在本節中,我們將 UWP 專案新增至解決方案,並修改該專案中預設的應用程式類別,以衍生自 Windows 社群工具組提供的 Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication 類別。 這個類別支援 IXamlMetadataProvider 介面,該介面可讓您的應用程式在執行時探索和載入自訂 UWP XAML 控制項的中繼資料,而這些中繼資料位於應用程式目前目錄組件中。 該類別也會初始化目前執行緒的 UWP XAML 架構。

  1. [方案總管] 中,在方案節點上按一下滑鼠右鍵,然後選取 [新增]>[新增專案]

  2. 選取 C# 空白應用程式 (通用 Windows) 專案範本。 將專案名稱設定為 MyUWPApp ,這樣您就不需要編輯本主題中的任何步驟或原始程式碼。 將目標版本最低版本設定為 Windows 10 版本 1903 (組建 18362) 或更新版本。

    注意

    請務必不要在 MyWPFApp 的子資料夾中建立 MyUWPApp。 如果您這樣做,MyWPFApp 會嘗試建置 UWP XAML 標記,就如同 WPF XAML 一樣。

  3. MyUWPApp 中,安裝 Microsoft.Toolkit.Win32.UI.XamlApplication NuGet 套件 (最新的穩定版本)。 上一節會說明安裝 NuGet 套件的處理程序。

  4. MyUWPApp中,開啟 App.xaml 檔案,並以下列 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. 同樣地,開啟 App.xaml.cs,並以下列程式碼取代其內容:

    namespace MyUWPApp
    {
        public sealed partial class App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
        {
            public App()
            {
                this.Initialize();
            }
        }
    }
    
  6. 刪除 MainPage.xamlMainPage.xaml.cs 檔案。

  7. 建置 MyUWPApp 專案。

在 MyWPFApp 中,新增 MyUWPApp 專案的參考

  1. MyWPFApp的專案檔中指定相容的架構版本,如下所示:

    1. 在 [方案總管]中,按一下 [MyWPFApp 專案節點],以在編輯器中開啟專案檔。

    2. 在第一個 PropertyGroup 元素內,新增下列子元素。 視需要變更值的 19041 部分,以符合 MyWPFApp 專案的目標和最低作業系統組建。

      <AssetTargetFallback>uap10.0.19041</AssetTargetFallback>
      
  2. [方案總管]中,以滑鼠右鍵按一下 [MyWPFApp]>[相依性],選擇 [新增專案參考],然後新增 MyUWPApp 專案的參考。

在 MyWPFApp 的進入點中具現化 XamlApplication 物件

接下來,將程式碼新增至 MyWPFApp 的進入點,以建立剛才在 MyUWPApp 中定義的應用程式類別的執行個體 (衍生自 XamlApplication 的類別)。

  1. 以滑鼠右鍵按一下 [MyWPFApp] 專案節點,選取 [新增]>[新增專案],然後選取 [類別]。 將名稱設定為 Program.cs,然後按一下 [新增]。

  2. Program.cs 的內容取代為下列 XAML (然後儲存檔案並建置 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. 以滑鼠右鍵按一下 [MyWPFApp 專案節點],然後選擇 [屬性]。

  4. Application>General中,按一下 [Startup 物件] 下拉式清單,然後選擇 MyWPFApp.Program (這是您剛才新增 Program 類別的完整名稱)。 如果您沒有看到它,請嘗試關閉並重新開啟 Visual Studio。

    注意

    根據預設,WPF 專案會在產生的程式碼檔案中定義 Main 進入點函式,而該檔案並非要修改。 上述步驟會將專案的進入點變更為新 Program 類別的 Main 方法,這可讓您儘快在應用程式的啟動程序中新增執行的程式碼。

  5. 將您的變更儲存至專案屬性。

使用包裝的控制項來裝載 InkCanvas 和 InkToolbar

既然您已將專案設定為使用 UWP XAML Islands,您就可以將 InkCanvasInkToolbar 包裝的 UWP XAML 控制項新增至應用程式。

  1. MyWPFApp中,開啟 MainWindow.xaml 檔案。

  2. 在靠近 XAML 檔案頂端的 Window 元素中,新增下列屬性。 此屬性會參考 InkCanvasInkToolbar 包裝 UWP XAML 控制項的 XAML 命名空間,並將它對應至 XML 命名空間控制項

    xmlns:controls="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls"
    
  3. 仍在 MainWindow.xaml 中,編輯現有的 Grid 元素,使其看起來像以下的 XAML。 此 XAML 在格線上新增一個 InkCanvas 和一個 InkToolbar 控制項 (前面加上您在上一個步驟中定義的控制項 XML 命名空間)。

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

    注意

    您也可以將這些和其他已包裝的控制項,從 [工具箱][Windows 社群工具組] 區段拖曳至設計工具,藉此新增到視窗

  4. 儲存 MainWindow.xaml

    如果您的裝置支援數位畫筆 (例如 Surface),而且您正在實體電腦上追蹤,則您現在可以建置並執行應用程式,並使用手寫筆在螢幕上繪製數位筆跡。 但是,如果您嘗試使用滑鼠撰寫,則不會發生任何事,因為根據預設,inkCanvas 只會針對數位筆啟用。 以下說明如何為滑鼠啟用 InkCanvas

  5. 仍在 MyWPFApp中,開啟 MainWindow.xaml.cs

  6. 將下列命名空間指示詞新增至檔案頂端:

    using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT;
    
  7. 找出 MainWindow 建構函式。 在呼叫 InitializeComponent之後,立即加入下列程式碼行:

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

    您可以使用 InkPresenter 物件來自訂預設筆跡體驗。 上述程式碼會使用 InputDeviceTypes 屬性來啟用滑鼠和手寫筆輸入。

  8. 儲存、建置及執行。 如果您使用電腦搭配滑鼠,請確認您可使用滑鼠在筆跡畫布空間中繪製某些內容。

使用主控制項裝載 CalendarView

在本節中,我們將使用 WindowsXamlHost 控制項,將 CalendarView 新增至應用程式。

注意

WindowsXamlHost 控制項是由 Microsoft.Toolkit.Wpf.UI.XamlHost套件所提供。 該套件隨附於您稍早安裝的 Microsoft.Toolkit.Wpf.UI.Controls 套件。

  1. [方案總管]中,在 MyWPFApp中,開啟 MainWindow.xaml 檔案。

  2. 在靠近 XAML 檔案頂端的 Window 元素中,新增下列屬性。 這個屬性會參考 WindowsXamlHost 控制項的 XAML 命名空間,並將它對應至 xamlhost XML 命名空間。

    xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
    
  3. 仍在 MainWindow.xaml 中,編輯現有的 Grid 元素,使其看起來像以下的 XAML。 此 XAML 在格線上新增一個 WindowsXamlHost 控制項 (前面加上您在上一個步驟中定義的 xamlhost XML 命名空間)。 若要裝載 UWP CalendarView 控制項,此 XAML 會將 InitialTypeName 屬性設定為控制項的完整名稱。 此 XAML 也會定義 ChildChanged 事件的事件處理常式,已轉譯裝載的控制項時會引發此事件。

    <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. 儲存 MainWindow.xaml,然後開啟 MainWindow.xaml.cs

  5. 刪除我們在上一節中新增的這一行程式碼:myInkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Pen;

  6. 將下列命名空間指示詞新增至檔案頂端:

    using Microsoft.Toolkit.Wpf.UI.XamlHost;
    
  7. 將下列 ChildChanged 事件處理常式方法新增至 MainWindow 類別。 轉譯主控制項時,這個事件處理常式會執行並建立行事曆控制項 SelectedDatesChanged 事件的簡單事件處理常式。

    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. 儲存、建置及執行。 確認行事曆控制項會顯示在視窗中,並在您選取日期時顯示訊息方塊。

封裝應用程式

您可選擇性地在 MSIX 套件中封裝 WPF 應用程式以供部署。 MSIX 是適用於 Windows 的新式且可靠的應用程式封裝技術。

下列指示說明如何使用 Visual Studio 中的 Windows 應用程式封裝專案,將解決方案中的所有元件封裝成 MSIX 套件 (請參閱 在 Visual Studio 中設定 MSIX 封裝的傳統型應用程式)。 只有當您想要在 MSIX 套件中封裝 WPF 應用程式時,才需要執行這些步驟。

注意

如果您選擇不要在 MSIX 封裝中封裝應用程式以供部署,則執行您應用程式的電腦必須安裝 Visual C++ Runtime

  1. 將新專案新增至從 Windows 應用程式封裝專案專案範本建立的解決方案中。 當您建立專案時,請選取和您為 UWP 專案所選取的值相同的 [目標版本] 和 [最小版本]

  2. 在封裝專案中,以滑鼠右鍵按一下 [相依性節點],然後選擇 [新增專案參考]。在專案清單中,選取 [MyWPFApp],然後按一下 [確定]。

    注意

    如果您想要在 Microsoft Store 中發佈您的應用程式,則也必須在封裝專案中新增 UWP 專案的參考。

  3. 如果您遵循此步驟,則解決方案中的所有專案都會以相同的特定平台 (x86 或 x64) 為目標。 為了使用 Windows 應用程式封裝專案,將 WPF 應用程式建置到 MSIX 套件中,這是必要的。 若要確認,您可以依照下列步驟執行:

    1. [方案總管] 中,以滑鼠右鍵按一下方案節點 (專案節點),然後選擇 [屬性]
    2. 選取左側 [組態屬性]。
    3. 按一下 [組態管理員] 按鈕。
    4. 確認所有列出的專案在 Platform 下具有相同的值:x86x64
  4. 以滑鼠右鍵按一下您剛才新增之封裝專案的專案節點,然後按一下 [設定為啟始專案]。

  5. 建置和執行封裝專案。 確認 WPF 應用程式執行,且 UWP 控制項如預期般顯示。

  6. 如需散發/部署封裝的相關資訊,請參閱管理 MSIX 部署