次の方法で共有


Windows ランタイム 8.x プロジェクトを UWP プロジェクトに移植する

移植プロセスを開始する際には、2 つのオプションがあります。 1 つは、アプリ パッケージ マニフェストを含む既存のプロジェクト ファイルのコピーを編集することです (そのオプションについては、アプリを ユニバーサル Windows プラットフォーム (UWP) に移行するのプロジェクト ファイルの更新に関する情報を参照してください)。 もう 1 つのオプションは、Visual Studio で新しい Windows 10 プロジェクトを作成し、ファイルをコピーすることです。 このトピックの最初のセクションでは、2 番目のオプションについて説明しますが、トピックの残りの部分には両方のオプションに適用できる追加情報があります。 また、新しい Windows 10 プロジェクトを既存のプロジェクトと同じソリューションに保持し、共有プロジェクトを使用してソース コード ファイルを共有することもできます。 または、Visual Studio のリンクされたファイル機能を使用して、新しいプロジェクトを独自のソリューションに保持し、ソース コード ファイルを共有することもできます。

プロジェクトを作成し、ファイルをコピーする

これらの手順では、Visual Studio で新しい Windows 10 プロジェクトを作成し、そのプロジェクトにファイルをコピーするオプションに焦点を当てます。 作成するプロジェクトの数とコピーするファイルに関する詳細の一部は、 ユニバーサル 8.1 アプリがある場合 およびその後のセクションで説明されている要因と決定によって異なります。 これらの手順では、最も単純なケースを想定しています。

  1. Microsoft Visual Studio 2015 を起動し、"新しいアプリケーション (Windows ユニバーサル)" プロジェクトを新規作成します。 詳細については、テンプレート (C#、C++、Visual Basic) を使った Windows ランタイム 8.x アプリ開発の開始に関する記事を参照してください。 新しいプロジェクトによって、すべてのデバイス ファミリで実行される 1 つのアプリ パッケージ (appx ファイル) が構築されます。
  2. ユニバーサル 8.1 アプリ プロジェクトで、再利用するすべてのソース コード ファイルとビジュアル アセット ファイルを特定します。 エクスプローラーを使って、データ モデル、ビュー モデル、ビジュアル アセット、リソース ディクショナリ、フォルダー構造、および再利用するその他すべての要素を、新しいプロジェクトにコピーします。 必要に応じて、ディスクにサブフォルダーをコピーするか、作成します。
  3. ビュー (MainPage.xaml や MainPage.xaml.cs など) も新しいプロジェクトにコピーします。 ここでも、必要に応じて新しいサブフォルダーを作成し、プロジェクトから既にあるビューを削除します。 ただし、Visual Studio が生成したビューを上書きまたは削除する前に、後で参照するときに役立つ場合があるため、コピーを保存しておきます。 ユニバーサル 8.1 アプリを移植する最初のフェーズでは、1 つのデバイス ファミリで適切に動作するようにアプリを適切に表示することに重点を置いています。 その後で、すべてのフォーム ファクターに対してビューを適切に対応させることに重点を置きます。必要に応じて、特定のデバイス ファミリを最大限に活用できるように、アダプティブ コードを追加します。
  4. ソリューション エクスプローラーで、 [すべてのファイルを表示] がオンであることを確認します。 コピーしたファイルを選択して右クリックし、[プロジェクトに含める] をクリックします。 これによって、含まれるフォルダーが自動的に取り込まれます。 後で必要に応じて、[すべてのファイルを表示] をオフに切り替えることができます。 代替ワークフローとして、[既存項目の追加] コマンドを使って Visual Studio ソリューション エクスプローラーで必要なすべてのサブフォルダーを作成することもできます。 ビジュアル アセットで、[ビルド アクション][コンテンツ] に設定されており、[出力ディレクトリにコピー][コピーしない] に設定されていることを確認します。
  5. この段階でビルド エラーが発生する可能性があります。 ただし、何を変更する必要があるかがわかっている場合は、Visual Studio の Find および Replace コマンドを使用してソース コードを一括変更できます。Visual Studio の命令型コード エディターでは、コンテキスト メニューの Resolve および Organize Usings コマンドを使用して、より対象を絞った変更を行うことができます。

マークアップとコードを最大限に再利用する

若干のリファクタリングを行い、アダプティブ コード (後で説明します) を追加することで、すべてのデバイス ファミリで動作するマークアップとコードを最大限に活用することができます。 詳しい説明を次に示します。

  • すべてのデバイス ファミリに共通するファイルについては、特に考慮する必要はありません。 これらのファイルは、実行対象となるすべてのデバイス ファミリで、アプリが使うファイルです。 これには、XAML マークアップ ファイル、命令型ソース コード ファイル、アセット ファイルが含まれます。
  • 実行されているデバイス ファミリをアプリで検出し、そのデバイス ファミリ専用に設計されたビューに移動させることができます。 詳しくは、「アプリが実行されているプラットフォームの検出」をご覧ください。
  • 代替手段がない場合に役立つ同様の手法は、マークアップ ファイルまたは ResourceDictionary ファイル (またはファイルを含むフォルダー) に特別な名前を付け、アプリが特定のデバイス ファミリで実行されている場合にのみ実行時に自動的に読み込まれるような方法です。 この手法については、「Bookstore1」のケース スタディをご覧ください。
  • Windows 10 のみをサポートする必要がある場合は、ユニバーサル 8.1 アプリのソース コードで多くの条件付きコンパイル ディレクティブを削除できます。 このトピックの Conditional コンパイルとアダプティブ コード を参照してください。
  • すべてのデバイス ファミリで使用できない機能 (プリンター、スキャナー、カメラ ボタンなど) を使用するには、アダプティブ コードを記述できます。 このトピックの「条件付きコンパイルとアダプティブ コード」に記載されている 3 番目の例をご覧ください。
  • Windows 8.1、Windows Phone 8.1、および Windows 10 をサポートする場合は、3 つのプロジェクトを同じソリューションに保持し、共有プロジェクトとコードを共有できます。 または、プロジェクト間でソース コード ファイルを共有することもできます。 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

ユニバーサル 8.1 アプリが既に呼び出しているWindows ランタイム API のほとんどは、ユニバーサル デバイス ファミリと呼ばれる一連の API に実装されています。 ただし、一部の API は拡張 SDK に実装されており、Visual Studio で認識されるのは、アプリのターゲット デバイス ファミリによって実装された API、または参照している拡張 SDK によって実装された API のみです。

検出できなかった名前空間、型、メンバーについてのコンパイル エラーが発生した場合は、上記のことが原因となる可能性があります。 API リファレンス ドキュメントで API のトピックを表示し、要件に関するセクションに移動します。このセクションでは、どのようなデバイス ファミリが API を実装するかが示されています。 ターゲット デバイス ファミリが示されていない場合は、プロジェクトで API を利用できるようにするために、そのデバイス ファミリ用の拡張 SDK に対する参照が必要になります。

[プロジェクト]>[参照の追加]>[Windows ユニバーサル]>[拡張機能] の順にクリックし、適切な拡張 SDK を選びます。 たとえば、呼び出す API がモバイル デバイス ファミリでのみ利用可能であり、それらの API がバージョン 10.0.x.y で導入されている場合は、[Windows Mobile Extensions for the UWP] を選びます。

これにより、次の参照がプロジェクト ファイルに追加されます。

<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 を実装するデバイス ファミリがアプリのターゲットではない場合は、ApiInformation クラスを使って、API を呼び出す前に API の有無をテストする必要があります (これはアダプティブ コードと呼ばれます)。 このテストの条件は、アプリの実行時に必ず評価されますが、API が存在するデバイスに対してのみ true と評価され、呼び出しが可能になります。 ユニバーサル API が存在するかどうかを最初に確認した後では、拡張 SDK とアダプティブ コードのみを使います。 次のセクションで、例をいくつか示します。

アプリ パッケージ マニフェスト」もご覧ください。

条件付きコンパイルとアダプティブ コード

コード ファイルが Windows 8.1 と Windows Phone 8.1 の両方で動作するように条件付きコンパイル (C# プリプロセッサ ディレクティブを使用) を使用している場合は、Windows 10 での収束作業に照らして、その条件付きコンパイルを確認できるようになりました。 収束とは、Windows 10 アプリでは、一部の条件を完全に削除できることを意味します。 他のユーザーは、次の例に示すように、実行時チェックに変更されます。

1 つのコード ファイルで Windows 8.1、Windows Phone 8.1、Windows 10 をサポートする場合も、同様の確認作業を実行できます。 プロジェクトのプロパティ ページで Windows 10 プロジェクトを確認すると、プロジェクトで条件付きコンパイル シンボルとして WINDOWS_UAP が定義されていることがわかります。 このため、このシンボルを WINDOWS_APP や WINDOWS_PHONE_APP と組み合わせて使うことができます。 これらの例では、ユニバーサル 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 では、ハードウェアの "カメラ" ボタンはモバイル デバイス ファミリに固有の概念です。 1 つのアプリ パッケージがすべてのデバイスで実行されるため、アダプティブ コードと呼ばれる手法を使って、コンパイル時の条件を実行時の条件に変更します。 そのためには、ApiInformation クラスを使って、実行時に HardwareButtons クラスの有無を照会します。 HardwareButtons は、モバイル拡張 SDK で定義されているため、その SDK への参照をプロジェクトに追加して、このコードをコンパイルする必要があります。 ただし、ハンドラーはモバイル拡張 SDK で定義されている型を実装するデバイスでのみ実行されることに注意してください。このようなデバイスは、モバイル デバイス ファミリに該当します。 したがって、このコードは、存在する機能のみを使用するように注意するという点で、ユニバーサル 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 のパッケージ マニフェスト スキーマ 参照に対する変更を示します。 スキーマ内のすべての要素、属性、および型のリファレンス情報については、「 Element Hierarchy」を参照してください。 Windows Phone ストア アプリを移植する場合、またはアプリが Windows Phone ストアからアプリに更新される場合は、 mp:PhoneIdentity 要素が以前のアプリのアプリ マニフェスト内にあるものと一致していることを確認します (ストアによってアプリに割り当てられたのと同じ GUID を使用します)。 これにより、Windows 10 または Windows 11 にアップグレードするアプリのユーザーは、重複ではなく、更新プログラムとして新しいアプリを受け取ります。 詳細については、 mp:PhoneIdentity リファレンス トピックを参照してください。

プロジェクトの設定 (すべての拡張 SDK の参照を含む) により、アプリが呼び出すことができる API サーフェス領域が決定されます。 ただし、ユーザーがアプリをストアからインストールできる実際のデバイスのセットを決定するのは、アプリ パッケージ マニフェストです。 詳細については、 TargetDeviceFamily の例を参照してください。

アプリ パッケージ マニフェストを編集して、一部の機能に必要なさまざまな宣言、機能、およびその他の設定を設定できます。 Visual Studio アプリ パッケージ マニフェスト エディターを使って、編集できます。 ソリューション エクスプローラーが表示されていない場合は、[表示] メニューから選択します。 Package.appxmanifest をダブルクリックします。 マニフェスト エディター ウィンドウが開きます。 適切なタブを選択して変更を加え、保存します。

次のトピックは「トラブルシューティング」です。