將 Windows 執行階段 8.x 專案移植到 UWP 專案
開始移植程序時,您有兩個選擇。 一個選擇是編輯現有專案檔案的副本,包括應用程式套件資訊清單 (有關該選項,請參閱將應用程式移轉到通用 Windows 平台 (UWP) 中有關更新專案檔案的資訊)。 另一個選擇是在 Visual Studio 中建立新的 Windows 10 專案,並將檔案複製到其中。 本主題的第一節會介紹第二個選項,但本主題的其餘章節囊括了適用於這兩個選項的其他資訊。 您也可以選擇將新的 Windows 10 專案保留在與現有專案相同的解決方案中,並使用共用專案共用原始程式碼檔案。 或者,您可以將新專案保留在自己的解決方案中,並使用 Visual Studio 中的連結檔案功能共用原始程式碼檔案。
建立專案並將檔案複製到其中
這些步驟重點介紹在 Visual Studio 中建立新的 Windows 10 專案,並將檔案複製到其中的選項。 部分具體細節 (如要建立的專案數量,以及要複製哪些檔案) 將取決於如果您有 Universal 8.1 應用程式,及後續各節中所述的因素和決策。 這些步驟會假設最簡單的情況。
- 啟動 Microsoft Visual Studio 2015,並建立新的空白應用程式 (Windows 通用) 專案。 有關詳細信息,請參閱使用範本快速啟動 Windows 執行階段 8.x 應用程式 (C#、C++、Visual Basic)。 您的新專案將會建置一個可在所有裝置系列上執行的應用程式套件 (appx 檔案)。
- 在您的 Universal 8.1 應用程式專案中,確定要重複使用的所有原始程式碼檔案和視覺資源檔案。 使用「檔案總管」,將資料模型、檢視模型、視覺資產、資源字典、資料夾結構,以及您希望重複使用的任何其他內容複製到新專案中。 根據需要在磁碟上複製或建立子資料夾。
- 將檢視 (例如 MainPage.xaml 和 MainPage.xaml.cs) 也複製到新的專案。 同樣地,根據需要建立新的子資料夾,並從專案中移除現有檢視。 但是,在覆寫或移 Visual Studio 產生的檢視之前,請保留一份副本,因為稍後可能會參考它。 移植 Universal 8.1 應用程式的第一階段重點是使其在一個裝置系列上看起來美觀並運作良好。 稍後,您將把注意力轉向確保檢視能順暢適應所有外形規格,並可選擇性地新增任何調適型程式碼,以充分利用特定裝置系列。
- 在 [方案總管] 中,確定 [顯示所有檔案] 已切換成開啟。 選擇您複製的檔案,對其按右鍵,然後按一下加入至專案。 這將自動加入其包含的資料夾。 您可以視需要關閉顯示所有檔案。 如果您想要的話,另一個工作流程是使用新增現有項目命令,並在 Visual Studio 方案總管中建立必要的子資料夾。 仔細檢查您的視覺資產是否已將建置動作設為內容,並將複製到輸出目錄設為不要複製。
- 在此階段,您可能會看到一些建置錯誤。 但是,如果您知道需要變更什麼,則可以使用 Visual Studio 的尋找和取代命令,對原始程式碼進行大量變更;在 Visual Studio 的命令式程式碼編輯器中,使用操作功能表上的解析和組織使用命令進行更有針對性的變更。
盡量重複使用標記和程式碼
您會發現,稍微重構和/或新增調適型程式碼 (如下所述) 可最大化適用於所有裝置系列的標記和程式碼。 以下是詳細資料。
- 不需要特別考慮適用於所有裝置系列的檔案。 應用程式將在其執行的所有裝置系列上使用這些檔案。 這包括 XAML 標記檔案、命令式原始程式碼檔案和資產檔案。
- 您的應用程式可以偵測正在執行的裝置系列,並瀏覽到專為該裝置系列設計的檢視。 如需詳細資訊,請參閱偵測應用程式執行的平台。
- 如果沒有其他選擇,您可能會發現有用的類似技術是為標記檔案或ResourceDictionary 檔案 (或包含該檔案的資料夾) 指定一個特殊名稱,讓您的應用程式在特定裝置系列上執行時,才會在執行階段自動載入該名稱。 這項技術於 Bookstore1 案例研究中說明。
- 如果您只需要支援 Windows 10,則可以刪除 Universal 8.1 應用程式原始程式碼中的大量條件式編譯指示詞。 請參閱本主題中的條件式編譯和調適型程式碼。
- 若要使用的功能並非所有裝置系列都可用 (例如印表機、掃描器或相機按鈕),您可以編寫調適型程式碼。 請參閱本主題中的條件式編譯和調適型程式碼中的第三個範例。
- 如果您想要支援 Windows 8.1、Windows Phone 8.1 和 Windows 10,則可以將三個專案保留在相同解決方案中,並與共用專案共用程式碼。 或者,您可以在專案之間共用原始程式碼檔案。 作法如下:在 Visual Studio 中,右鍵按一下方案總管中的專案,選取新增現有項目,選擇要共用的檔案,然後按一下新增為連結。 將原始程式碼檔案儲存在檔案系統上的共用資料夾中,連結到這些檔案的專案可以看到它們。 並且不要忘記將它們新增到原始程式碼控制中。
- 若要在二進位層級 (而非原始程式碼層級) 重複使用這些原始程式碼檔案,請參閱在 C# 和 Visual Basic 中建立 Windows 執行階段元件。 還有可移植類別庫,支援 Windows 8.1、Windows Phone 8.1 和 Windows 10 應用程式 (.NET Core) 的 .NET Framework 中提供的 .NET API 子集,以及完整的 .NET Framework。 可移植類別庫組件與這些平台都是二進位相容的。 使用 Visual Studio 建立一個面向可移植類別庫的專案。 請參閱使用可移植類別庫進行跨平台開發。
擴充功能 SDK
Universal 8.1 應用程式呼叫的大多數 Windows 執行階段 API 都是在稱為通用裝置系列的 API 集中實作。 但是,有些是在擴充 SDK 中實作的,而 Visual Studio 只會識別由應用程式的目標裝置系列,或您所參考任何擴充 SDK 實作的 API。
如果您遇到無法找到命名空間、類型或成員的編譯錯誤,那麼這可能就是原因。 開啟 API 參考文件中的 API 主題,並瀏覽至「要求」一節:您將在此知道實作的裝置系列為何。 如果這不是您的目標裝置系列,那麼要讓 API 可用於您的裝置,您將需要參考該裝置系列的擴充 SDK。
按一下專案>新增參考>Windows 通用>擴充功能,並選擇適當的擴充 SDK。 例如,如果要呼叫的 API 僅可在行動裝置系列中使用,且它們是在版本 10.0.x.y 中引入的,則為 UWP 選擇 Windows 行動擴充功能。
這會將以下參考新增到您的專案檔案中:
<ItemGroup>
<SDKReference Include="WindowsMobile, Version=10.0.x.y">
<Name>Windows Mobile Extensions for the UWP</Name>
</SDKReference>
</ItemGroup>
名稱和版本號碼與 SDK 安裝位置中的資料夾相符。 例如,上述資訊符合此資料夾名稱:
\Program Files (x86)\Windows Kits\10\Extension SDKs\WindowsMobile\10.0.x.y
除非您的應用程式面向實作 API 的裝置系列,否則您需要在呼叫 API 之前使用 ApiInformation 類別來測試 API 是否存在 (這稱為調適型程式碼)。 然後,無論您的應用程式在何處執行,都會評估此條件,但僅在存在 API 並因此可供呼叫的裝置上評估為 True。 僅在先檢查通用 API 是否存在後,才使用擴充 SDK 和調適型程式碼。 下一節會提供一些範例。
另請參閱應用程式套件資訊清單。
條件式編譯和調適型程式碼
如果您使用條件式編譯 (使用 C# 預處理器指令) 來讓程式碼檔案可以在 Windows 8.1 和 Windows Phone 8.1 上執行,那麼您現在可以根據 Windows 10 中完成的收斂工作來檢查條件式編譯。 收斂代表在 Windows 10 應用程式中,可以完全移除某些條件。 其他變更為執行階段檢查,如以下範例所示。
注意 如果您想在單一程式碼檔案中支援 Windows 8.1、Windows Phone 8.1 和 Windows 10,那麼您也可以這樣做。 如果您查看 Windows 10 專案的專案屬性頁面,您將看到該專案將 WINDOWS_UAP 定義為條件式編譯符號。 因此,您可以將其與 WINDOWS_APP 和 WINDOWS_PHONE_APP 結合使用。 這些範例介紹了從 Universal 8.1 應用程式中移除條件式編譯,並取代 Windows 10 應用程式對等程式碼的簡單案例。
第一個範例說明 PickSingleFileAsync API (僅適用於 Windows 8.1) 和 PickSingleFileAndContinue API (僅適用於 Windows Phone 8.1) 的使用模式。
#if WINDOWS_APP
// Use Windows.Storage.Pickers.FileOpenPicker.PickSingleFileAsync
#else
// Use Windows.Storage.Pickers.FileOpenPicker.PickSingleFileAndContinue
#endif // WINDOWS_APP
Windows 10 融合了 PickSingleFileAsync API,因此您的程式碼可簡化為:
// Use Windows.Storage.Pickers.FileOpenPicker.PickSingleFileAsync
在此範例中,我們會處理硬體返回按鈕,但僅限於 Windows Phone。
#if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.BackPressed += this.HardwareButtons_BackPressed;
#endif // WINDOWS_PHONE_APP
...
#if WINDOWS_PHONE_APP
void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
{
// Handle the event.
}
#endif // WINDOWS_PHONE_APP
在 Windows 10 中,返回按鈕事件是通用概念。 在硬體或軟體中實作的返回按鈕都會引發 BackRequested 事件,因此必須要進行處理。
Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested +=
this.ViewModelLocator_BackRequested;
...
private void ViewModelLocator_BackRequested(object sender, Windows.UI.Core.BackRequestedEventArgs e)
{
// Handle the event.
}
最後一個範例與前一個範例類似。 在這裡,我們會處理硬體相機按鈕,但同樣,僅在編譯到 Windows Phone 應用程式套件中的程式碼中進行處理。
#if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.CameraPressed += this.HardwareButtons_CameraPressed;
#endif // WINDOWS_PHONE_APP
...
#if WINDOWS_PHONE_APP
void HardwareButtons_CameraPressed(object sender, Windows.Phone.UI.Input.CameraEventArgs e)
{
// Handle the event.
}
#endif // WINDOWS_PHONE_APP
在 Windows 10 中,硬體相機按鈕是行動裝置系列的特有概念。 由於我們要讓一個應用程式套件能在所有裝置上執行,因此使用所謂的調適型程式碼將編譯階段條件變更為執行階段條件。 若要這麼做,我們使用 ApiInformation 類別在執行階段查詢 HardwareButtons 類別是否存在。 HardwareButtons 是在行動擴充 SDK 中定義的,因此我們需要將對該 SDK 的參考新增到專案中,以便編譯此程式碼。 但請注意,處理常式只會在實作行動擴充 SDK 中所定義類型的裝置上執行,即行動裝置系列。 因此,該程式碼相當於 Universal 8.1 程式碼,因為它只小心地使用現有的功能,儘管它以不同的方式達成目標。
// Note: Cache the value instead of querying it more than once.
bool isHardwareButtonsAPIPresent = Windows.Foundation.Metadata.ApiInformation.IsTypePresent
("Windows.Phone.UI.Input.HardwareButtons");
if (isHardwareButtonsAPIPresent)
{
Windows.Phone.UI.Input.HardwareButtons.CameraPressed +=
this.HardwareButtons_CameraPressed;
}
...
private void HardwareButtons_CameraPressed(object sender, Windows.Phone.UI.Input.CameraEventArgs e)
{
// Handle the event.
}
另請參閱偵測應用程式執行的平台。
應用程式套件資訊清單
Windows 10 中的變更內容主題列出了 Windows 10 的套件資訊清單結構描述參考的變更,包括已新增、移除和變更的元素。 有關結構描述中所有元素、屬性和類型的參考訊息,請參閱元素階層。 如果您要移植 Windows Phone Store 應用程式,或者您的應用程式是Windows Phone Store 應用程式的更新內容,請確保 mp:PhoneIdentity 元素與先前應用程式的應用程式資訊清單中的內容相符 (使用商店指派給應用程式的相同 GUID)。 這將確保升級到 Windows 10 或 Windows 11 的應用程式使用者將收到您的新應用程式作為更新,而不是重複的應用程式。 如需詳細資訊,請參閱 mp:PhoneIdentity 參考主題。
專案中的設定 (包括任何擴充 SDK 參考) 決定了您的應用程式可以呼叫的 API 介面區。 但是,您的應用程式套件資訊清單決定了客戶可從商店安裝您應用程式的實際裝置集。 有關詳細資訊,請參閱 TargetDeviceFamily 中的範例。
您可以編輯應用程式套件資訊清單,以設定某些功能所需的各種宣告、功能和其他設定。 您可以使用 Visual Studio 應用程式套件資訊清單編輯器來進行編輯。 如果方案總管沒有顯示,請從檢視功能表中選擇它。 按兩下 Package.appxmanifest。 這將開啟資訊清單編輯器視窗。 選取適當的索引標籤進行變更,然後儲存。
下一個主題是疑難排解。