將 Windows 執行階段 8.x 專案移植到 UWP 專案Porting a Windows Runtime 8.x project to a UWP project

當您開始移植程序時,會有兩個選項。You have two options when you begin the porting process. 其中一個是編輯現有專案檔案的複本,包括應用程式套件資訊清單 (若要了解該選項,請參閱將 app 移轉至通用 Windows 平台 (UWP) 中關於更新您專案檔案的資訊)。One is to edit a copy of your existing project files, including the app package manifest (for that option, see the info about updating your project files in Migrate apps to the Universal Windows Platform (UWP)). 另一個選項是在 Visual Studio 中建立新的 Windows 10 專案,並將檔案複製到其中。The other option is to create a new Windows 10 project in Visual Studio and copy your files into it. 本主題的第一節會說明第二個選項,但本主題的其餘部分則會包含其他適用於這兩個選項的資訊。The first section in this topic describes that second option, but the rest of the topic has additional info applicable to both options. 您也可以選擇將新的 Windows 10 專案和您的現有專案保留在同一個方案中,並使用共用專案來共用原始程式碼檔案。You can also choose to keep your new Windows 10 project in the same solution as your existing projects and share source code files using a shared project. 或者,您可以在方案中保留新專案,並在 Visual Studio 中使用連結檔案的功能共用原始程式碼檔案。Or, you can keep the new project in a solution of its own and share source code files using the linked files feature in Visual Studio.

建立專案並將檔案複製到其中Create the project and copy files to it

這些步驟著重在 Visual Studio 中建立新的 Windows 10 專案,並將檔案複製到其中的選項。These steps focus on the option to create a new Windows 10 project in Visual Studio and copy your files into it. 一些有關您建立的專案數量以及要複製哪些檔案的特定內容,取決於如果您有通用 8.1 應用程式與其中各小節中所述的因素與決策。Some of the specifics around how many projects you create, and which files you copy over, will depend on the factors and decisions described in If you have a Universal 8.1 app and the sections that follow it. 這些步驟假設最簡單的情況。These steps assume the simplest case.

  1. 啟動 Microsoft Visual Studio 2015,並建立新的空白應用程式 (Windows 通用) 專案。Launch Microsoft Visual Studio 2015 and create a new Blank Application (Windows Universal) project. 如需詳細資訊,請參閱 使用 (c #、c + +、Visual Basic) 的範本來開始 Windows 執行階段8.x 應用程式 For more info, see Jumpstart your Windows Runtime 8.x app using templates (C#, C++, Visual Basic). 新專案建置的應用程式套件 (appx 檔案) 將在所有裝置系列執行。Your new project builds an app package (an appx file) that will run on all device families.
  2. 在通用 8.1 應用程式專案中,找出您想要重複使用的所有原始程式碼檔案及視覺資產檔案。In your Universal 8.1 app project, identify all the source code files and visual asset files that you want to reuse. 使用 [檔案總管],將資料模型、檢視模型、視覺資產、資源字典、資料夾結構,以及任何您想要重複使用的其他項目複製到新專案。Using File Explorer, copy data models, view models, visual assets, Resource Dictionaries, folder structure, and anything else that you wish to re-use, to your new project. 視需要在磁碟上複製或建立子資料夾。Copy or create sub-folders on disk as necessary.
  3. 將檢視 (例如 MainPage.xaml 和 MainPage.xaml.cs) 一併複製到新專案。Copy views (for example, MainPage.xaml and MainPage.xaml.cs) into the new project, too. 同樣地,請視需要建立新的子資料夾,然後從專案移除現有的檢視。Again, create new sub-folders as necessary, and remove the existing views from the project. 但是在您覆寫或移除 Visual Studio 產生的檢視之前,請保留一份複本,因為可能稍後可用來供參考。But, before you over-write or remove a view that Visual Studio generated, keep a copy because it may be useful to refer to it later. 移植通用 8.1 應用程式的第一個階段著重在美化外觀以及能在裝置系列上運作良好。The first phase of porting a Universal 8.1 app focuses on getting it to look good and work well on one device family. 稍後,您會將重點放在確認檢視能隨所有尺寸規格適當調整,也可以新增任何調適型程式碼,以充分利用特定的裝置系列。Later, you'll turn your attention to making sure the views adapt themselves well to all form factors, and optionally to adding any adaptive code to get the most from a particular device family.
  4. 在 [方案總管] 中,確定 [顯示所有檔案] 已切換成開啟。In Solution Explorer, make sure Show All Files is toggled on. 選取您複製的檔案,在這些檔案上按一下滑鼠右鍵,然後按一下 [加入至專案]Select the files that you copied, right-click them, and click Include In Project. 這將會自動包含它們的容器資料夾。This will automatically include their containing folders. 然後您可以視需要將 [顯示所有檔案] 切換成關閉。You can then toggle Show All Files off if you like. 如果您想要的話,也可以選擇替代的工作流程,就是先在 Visual Studio [方案總管] 中建立任何必要的子資料夾,然後使用 [加入現有項目]命令。An alternative workflow, if you prefer, is to use the Add Existing Item command, having created any necessary sub-folders in the Visual Studio Solution Explorer. 仔細檢查您視覺資產的 [建置動作] 是否已設定為 [內容],而 [複製到輸出目錄] 是否已設定為 [不要複製]Double-check that your visual assets have Build Action set to Content and Copy to Output Directory set to Do not copy.
  5. 您在這個階段可能會看到一些建置錯誤。You are likely to see some build errors at this stage. 但如果您知道需要變更什麼,就可以使用 Visual Studio 的 Find and Replace 命令針對原始碼進行大量變更;還可以在 Visual Studio 的命令式程式碼編輯器中使用內容功能表上的 ResolveOrganize Usings 命令,對更多目標項目做出變更。But, if you know what you need to change, then you can use Visual Studio's Find and Replace command to make bulk changes to your source code; and in the imperative code editor in Visual Studio, use the Resolve and Organize Usings commands on the context menu for more targeted changes.

儘可能重複使用標記與程式碼Maximizing markup and code reuse

您將發現重構一些和/或新增調適型程式碼 (其會在下面說明),可讓您儘可能重複使用可跨所有裝置系列運作的標記與程式碼。You will find that refactoring a little, and/or adding adaptive code (which is explained below), will allow you to maximize the markup and code that works across all device families. 以下是更多詳細資料。Here are more details.

  • 所有裝置系列都通用的檔案不需要特殊考量。Files that are common to all device families need no special consideration. 那些檔案將由所有裝置系列上執行的應用程式使用。Those files will be used by the app on all the device families that it runs on. 這包括 XAML 標記檔案、命令式原始程式碼檔案以及資產檔案。This includes XAML markup files, imperative source code files, and asset files.
  • 您的應用程式能夠偵測到執行的裝置系列,並瀏覽到專為該裝置系列設計的檢視。It is possible for your app to detect the device family that it is running on and navigate to a view that has been designed specifically for that device family. 如需詳細資訊,請參閱偵測執行您 app 的平台For more details, see Detecting the platform your app is running on.
  • 有項可能很有用的類似技術,就是在別無他法時,為標記檔案或 ResourceDictionary 檔案 (或包含該檔案的資料夾) 指定特殊名稱,如此一來,只有在特定裝置系列執行您的 App 時,才會於執行階段自動載入。A similar technique that you may find useful if there is no alternative is give a markup file or ResourceDictionary file (or the folder that contains the file) a special name such that it is automatically loaded at runtime only when your app runs on a particular device family. 此技術會在 Bookstore1 案例研究中說明。This technique is illustrated in the Bookstore1 case study.
  • 如果您只需要支援 Windows 10,應該能移除通用 8.1 應用程式原始程式碼中的許多條件式編譯指示詞。You should be able to remove a lot of the conditional compilation directives in your Universal 8.1 app's source code if you only need to support Windows 10. 請參閱本主題中的條件式編譯與調適型程式碼See Conditional compilation and adaptive code in this topic.
  • 若要使用並非所有裝置系列都適用的功能 (例如,印表機、掃描器或相機按鈕),您可以撰寫調適型程式碼。To use features that are not available on all device families (for example, printers, scanners, or the camera button), you can write adaptive code. 請參閱本主題中條件式編譯與調適型程式碼的第三個範例。See the third example in Conditional compilation and adaptive code in this topic.
  • 如果您想要支援 Windows 8.1、Windows Phone 8.1 及 Windows 10,可以將三個專案保留在同一個方案中,並使用共用專案共用程式碼。If you want to support Windows 8.1, Windows Phone 8.1, and Windows 10, then you can keep three projects in the same solution and share code with a Shared project. 或者,您可以在專案間共用原始程式碼檔案。Alternatively, you can share source code files between projects. 以下說明:在 Visual Studio 中,以滑鼠右鍵按一下 方案總管中的專案,選取 [ 加入現有專案],選取要共用的檔案,然後按一下 [ 新增為連結]。Here's how: in Visual Studio, right-click the project in Solution Explorer, select Add Existing Item, select the files to share, and then click Add As Link. 將您的原始程式碼檔案儲存在檔案系統上的通用資料夾中,這是連結到那些檔案的專案可看見它們的資料夾。Store your source code files in a common folder on the file system where the projects that link to them can see them. 同時別忘了將它們新增到原始檔控制。And don't forget to add them to source control.
  • 若要在二進位層級(而不是原始程式碼層級)重複使用,請參閱使用 c # 和 Visual Basic 建立 Windows 執行階段元件For reuse at the binary level, rather than the source code level, see Creating Windows Runtime components in C# and Visual Basic. 另外也有「可攜式類別庫」,這些類別庫支援適用於 Windows 8.1、Windows Phone 8.1 及 Windows 10 應用程式 (.NET Core) 的 .NET Framework 以及完整 .NET Framework 中提供的 .NET API 子集。There are also Portable Class Libraries, which support the subset of .NET APIs that are available in the .NET Framework for Windows 8.1, Windows Phone 8.1, and Windows 10 apps (.NET Core), and the full .NET Framework. 「可攜式類別庫」組件與這些平台皆二進位相容。Portable Class Library assemblies are binary compatible with all these platforms. 請使用 Visual Studio 來建立針對「可攜式類別庫」設計的專案。Use Visual Studio to create a project that targets a Portable Class Library. 請參閱使用可攜式類別庫進行跨平台開發See Cross-Platform Development with the Portable Class Library.

擴充功能 SDKExtension SDKs

通用 8.1 應用程式已經呼叫的大部分 Windows 執行階段 API 已經在稱為通用裝置系列的一組 API 中實作。Most of the Windows Runtime APIs your Universal 8.1 app already calls are implemented in the set of APIs known as the universal device family. 但是有些實作於擴充功能 SDK,而且 Visual Studio 只能辨識您的應用程式目標裝置系列或任何您參考的擴充功能 SDK 實作的 API。But, some are implemented in extension SDKs, and Visual Studio only recognizes APIs that are implemented by your app's target device family or by any extension SDKs that you have referenced.

如果您收到有關找不到命名空間或型別或成員的編譯錯誤,原因可能在此。If you get compile errors about namespaces or types or members that could not be found, then this is likely to be the cause. 開啟 API 參考文件中的 API 主題,並瀏覽到<需求>一節:文中會告訴您實作裝置系列為何。Open the API's topic in the API reference documentation and navigate to the Requirements section: that will tell you what the implementing device family is. 如果那不是您的目標裝置系列,則您必須擁有該裝置系列之擴充功能 SDK 的參考,您的專案才能使用 API。If that's not your target device family, then to make the API available to your project, you will need a reference to the extension SDK for that device family.

按一下 [ 專案 > 加入參考 > Windows 通用 > 延伸 模組],然後選取適當的延伸模組 SDK。Click Project > Add Reference > Windows Universal > Extensions and select the appropriate extension SDK. 例如,如果您想要呼叫的 Api 僅適用于行動裝置系列,而且是在 10.0. x. x. x. x. x. x 版中引進,則請選取 UWP 的 Windows Mobile ExtensionsFor example, if the APIs you want to call are available only in the mobile device family, and they were introduced in version 10.0.x.y, then select Windows Mobile Extensions for the UWP.

如此便會將下列參考加入您的專案檔案:That will add the following reference to your project file:

<ItemGroup>
    <SDKReference Include="WindowsMobile, Version=10.0.x.y">
        <Name>Windows Mobile Extensions for the UWP</Name>
    </SDKReference>
</ItemGroup>

名稱與版本號碼會和 SDK 安裝位置中的資料夾相符。The name and version number match the folders in the installed location of your SDK. 例如,上述資訊符合這個資料夾名稱:For example, the above information matches this folder name:

\Program Files (x86)\Windows Kits\10\Extension SDKs\WindowsMobile\10.0.x.y

除非您的 app 是專為實作 API 的裝置系列所設計,否則必須在呼叫之前,使用 ApiInformation 類別來測試該 API 是否存在 (這稱為調適型程式碼)。Unless your app targets the device family that implements the API, you'll need to use the ApiInformation class to test for the presence of the API before you call it (this is called adaptive code). 每當您的應用程式執行時都將會評估此條件,但只會將有 API 存在的裝置評估為 true,也才可供呼叫。This condition will then be evaluated wherever your app runs, but it will only evaluate to true on devices where the API is present and therefore available to call. 務必在檢查通用 API 是否存在之後,才使用擴充功能 SDK 與調適型程式碼。Only use extension SDKs and adaptive code after first checking whether a universal API exists. 下一節會提供一些範例。Some examples are given in the section below.

另請參閱應用程式套件資訊清單Also, see App package manifest.

條件式編譯與調適型程式碼Conditional compilation and adaptive code

如果您使用條件式編譯 (搭配使用 C# 前置處理器指示詞),以便您的程式碼檔案在 Windows 8.1 與 Windows Phone 8.1 上運作,有鑑於 Windows 10 中完成的交集工作,您現在可以檢閱所做的條件式編譯。If you're using conditional compilation (with C# preprocessor directives) so that your code files work on both Windows 8.1 and Windows Phone 8.1, then you can now review that conditional compilation in light of the convergence work done in Windows 10. 交集表示在 Windows 10 應用程式中,有些條件式可以全然移除。Convergence means that, in your Windows 10 app, some conditions can be removed altogether. 其他有關執行階段檢查的變更,如下列範例所示。Others change to run-time checks, as demonstrated in the examples below.

注意   如果您想要在單一程式碼檔案中支援 Windows 8.1、Windows Phone 8.1 和 Windows 10,也可以這麼做。Note   If you want to support Windows 8.1, Windows Phone 8.1, and Windows 10 in a single code file, then you can do that too. 如果您在 [專案屬性] 頁面上查看 Windows 10 專案,您會看到專案將 WINDOWS UAP 定義 _ 為條件式編譯符號。If you look in your Windows 10 project at the project properties pages, you'll see that the project defines WINDOWS_UAP as a conditional compilation symbol. 因此,您可以將它與 WINDOWS _ 應用程式和 windows _ PHONE _ 應用程式搭配使用。So, you can use that in combination with WINDOWS_APP and WINDOWS_PHONE_APP. 這些範例示範說明較簡單的情況,移除通用 8.1 應用程式的條件式編譯,然後取代為 Windows 10 應用程式的對等程式碼。These examples show the simpler case of removing the conditional compilation from a Universal 8.1 app and substituting the equivalent code for a Windows 10 app.

第一個範例示範 PickSingleFileAsync API (這只適用於 Windows 8.1) 與 PickSingleFileAndContinue API (這只適用於 Windows Phone 8.1) 的使用模式。This first example shows the usage pattern for the PickSingleFileAsync API (which applies only to Windows 8.1) and the PickSingleFileAndContinue API (which applies only to 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 交集,因此您的程式碼可簡化如下:Windows 10 converges on the PickSingleFileAsync API, so your code simplifies to this:

    // Use Windows.Storage.Pickers.FileOpenPicker.PickSingleFileAsync

我們在這個範例中處理硬體的返回按鈕—但僅限於 Windows Phone。In this example, we handle the hardware back button—but only on 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 中,返回按鈕事件是通用的概念。In Windows 10, the back button event is a universal concept. 實作於硬體或軟體的返回按鈕都會引發 BackRequested 事件,因此要處理的就是這個事件。Back buttons implemented in hardware or in software will all raise the BackRequested event, so that's the one to handle.

    Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested +=
        this.ViewModelLocator_BackRequested;

...

private void ViewModelLocator_BackRequested(object sender, Windows.UI.Core.BackRequestedEventArgs e)
{
    // Handle the event.
}

最後的這個範例類似於前一個範例。This final example is similar to the previous one. 我們在此處理的是硬體相機按鈕—但同樣僅限編譯至 Windows Phone 應用程式套件的程式碼。Here, we handle the hardware camera button—but again, only in the code compiled into the Windows Phone app package.

#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 中,硬體相機按鈕是行動裝置系列專屬的概念。In Windows 10, the hardware camera button is a concept particular to the mobile device family. 因為應用程式套件將在所有裝置上執行,所以我們將編譯階段條件變更為使用調適型程式碼的執行階段條件。Because one app package will be running on all devices, we change our compile-time condition into a run-time condition using what is known as adaptive code. 為此,我們使用 ApiInformation 類別查詢執行階段是否有 HardwareButtons 類別存在。To do that, we use the ApiInformation class to query at run-time for the presence of the HardwareButtons class. HardwareButtons 定義在行動裝置的擴充功能 SDK,因此我們必須將該 SDK 的參照新增到專案,以供編譯這個程式碼。HardwareButtons is defined in the mobile extension SDK, so we'll need to add a reference to that SDK to our project for this code to compile. 不過請注意,處理常式只會在實作行動裝置擴充功能 SDK 中定義的裝置類型上執行,那就是行動裝置系列。Note, though, that the handler will only be executed on a device that implements the types defined in the mobile extension SDK, and that's the mobile device family. 因此這個程式碼實質上等同於通用 8.1 程式碼,因為它很謹慎地僅使用現有的功能 (雖然是以不同的方式達成)。So, this code is morally equivalent to the Universal 8.1 code in that it is careful only to use features that are present, although it achieves that in a different way.

    // 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.
}

另請參閱偵測執行您 app 的平台Also, see Detecting the platform your app is running on.

應用程式套件資訊清單App package manifest

Windows 10 中的變更功能主題會針對 Windows 10 列出對套件資訊清單結構描述參考所做的變更,包括已新增、移除及變更的元素。The What's changed in Windows 10 topic lists changes to the package manifest schema reference for Windows 10, including elements that have been added, removed, and changed. 如需結構描述中所有元素、屬性和類型的參考資訊,請參閱元素階層For reference info on all elements, attributes, and types in the schema, see Element Hierarchy. 如果您正在移植 Windows Phone 市集應用程式,或您的 app 是 Windows Phone 市集中 app 的更新,請確定 pm:PhoneIdentity 元素符合上一個 app (使用市集指派給 app 的相同 GUID) 的應用程式資訊清單中的元素。If you're porting a Windows Phone Store app, or if your app is an update to an app from the Windows Phone Store, ensure that the pm:PhoneIdentity element matches what's in the app manifest of your previous app (use the same GUIDs that were assigned to the app by the Store). 這樣可確保應用程式使用者升級到 Windows 10 時,將會以更新方式 (而不是重複) 收到新的應用程式。This will ensure that users of your app who are upgrading to Windows 10 will receive your new app as an update, not a duplicate. 如需詳細資訊,請參閱 pm:PhoneIdentity 參考主題。See the pm:PhoneIdentity reference topic for more details.

您專案 (包括任何擴充功能 SDK 參考) 中的設定,會決定您應用程式能呼叫的 API 介面區。The settings in your project (including any extension SDKs references) determine the API surface area that your app can call. 但客戶實際上能夠透過市集安裝您應用程式的裝置集,是由您的應用程式套件資訊清單決定。But, your app package manifest is what determines the actual set of devices that your customers can install your app onto from the Store. 如需詳細資訊,請參閱 TargetDeviceFamily 中的範例。For more info, see examples in TargetDeviceFamily.

您可以編輯應用程式套件資訊清單,來設定各種宣告、功能及某些功能需要的其他設定。You can edit the app package manifest to set various declarations, capabilities, and other settings that some features need. 您可以使用 Visual Studio 應用程式套件資訊清單編輯器來編輯它。You can use the Visual Studio app package manifest editor to edit it. 如果未顯示 方案總管 ,請從 [ View ] 功能表中選擇它。If the Solution Explorer is not shown, choose it from the View menu. 按兩下 Package.appxmanifestDouble-click Package.appxmanifest. 資訊清單編輯器視窗隨即開啟。This opens the manifest editor window. 選取適當的索引標籤來進行變更,然後儲存。Select the appropriate tab to make changes and then save.

下一個主題是疑難排解The next topic is Troubleshooting.