Portieren Windows Phone Silverlight-Projekte zu UWP-Projekten

Das vorherige Thema war Namespace und Klassenzuordnungen.

Sie beginnen mit dem Portierungsprozess, indem Sie ein neues Windows 10-Projekt in Visual Studio erstellen und Ihre Dateien in das Projekt kopieren.

Erstellen des Projekts und Kopieren von Dateien in das Projekt

  1. Starten Sie Microsoft Visual Studio 2015, und erstellen Sie ein neues Projekt für leere Anwendungen (Windows Universal). Weitere Informationen finden Sie unter Jumpstart your Windows-Runtime 8.x app using templates (C#, C++, Visual Basic).For more info, see Jumpstart your Windows-Runtime 8.x app using templates (C#, C++, Visual Basic). Das neue Projekt erstellt ein App-Paket (eine AppX-Datei), das auf allen Gerätefamilien ausgeführt wird.
  2. Identifizieren Sie in Ihrem Windows Phone Silverlight-App-Projekt alle Quellcodedateien und visuellen Objektdateien, die Sie wiederverwenden möchten. Kopieren Sie mithilfe von Explorer Datenmodelle, Ansichtsmodelle, visuellen Ressourcen, Ressourcenverzeichnissen, Ordnerstruktur und allen anderen Elementen, die Sie wiederverwenden möchten, in Ihr neues Projekt. Kopieren oder erstellen Sie nach Bedarf Unterordner auf dem Datenträger.
  3. Kopieren Sie auch Ansichten (z. B. "MainPage.xaml" und "MainPage.xaml.cs") in den neuen Projektknoten. Erstellen Sie bei Bedarf neue Unterordner, und entfernen Sie die vorhandenen Ansichten aus dem Projekt. Bevor Sie jedoch eine von Visual Studio generierte Ansicht überschreiben oder entfernen, behalten Sie eine Kopie bei, da sie später nützlich sein kann. In der ersten Phase des Portierens einer Windows Phone Silverlight-App liegt der Schwerpunkt darauf, dass sie gut aussieht und auf einer Gerätefamilie gut funktioniert. Später wenden Sie sich an Ihre Aufmerksamkeit, um sicherzustellen, dass sich die Ansichten gut an alle Formfaktoren anpassen, und optional alle adaptiven Code hinzufügen, um die optimale Nutzung von einer bestimmten Gerätefamilie zu erzielen.
  4. Vergewissern Sie sich im Projektmappen-Explorer, dass Alle Dateien anzeigen aktiviert ist. Wählen Sie die kopierten Dateien aus, klicken Sie mit der rechten Maustaste darauf, und klicken Sie dann auf "In Projekt einschließen". Dies schließt automatisch deren enthaltenden Ordner ein. Sie können dann bei Bedarf die Option "Alle Dateien anzeigen" deaktivieren. Wenn Sie es vorziehen, verwenden Sie den Befehl "Vorhandenes Element hinzufügen", nachdem Sie alle erforderlichen Unterordner in Visual Studio Projektmappen-Explorer erstellt haben. Überprüfen Sie, ob ihre visuellen Ressourcen "Buildaktion" auf "Inhalt" und "In Ausgabeverzeichnis kopieren" auf "Nicht kopieren" festgelegt haben.
  5. Die Unterschiede bei Namespace- und Klassennamen führen zu vielen Buildfehlern in dieser Phase. Wenn Sie beispielsweise die von Visual Studio generierten Ansichten öffnen, sehen Sie, dass sie vom Typ "Page" und nicht "PhoneApplicationPage" sind. Es gibt viele Unterschiede zwischen XAML-Markup und imperativem Code, die in den folgenden Themen dieses Portierungshandbuchs ausführlich behandelt werden. Sie werden jedoch schnell fortschritte machen, indem Sie die folgenden allgemeinen Schritte ausführen: Ändern Sie "clr-namespace" in "using" in Ihren Namespacepräfixdeklarationen im XAML-Markup; verwenden Sie das Thema Namespace und Klassenzuordnungen sowie den Befehl "Suchen und Ersetzen" von Visual Studio, um Massenänderungen am Quellcode vorzunehmen (z. B. "System.Windows" durch "Windows.UI.Xaml"); und verwenden Sie im imperativen Code-Editor in Visual Studio die Befehle "Auflösen und Organisieren von Verwendungen" im Kontextmenü, um gezieltere Änderungen zu erhalten.

Erweiterungs-SDKs

Die meisten Universelle Windows-Plattform (UWP)-APIs, die Ihre portierte App aufruft, werden in der Gruppe von APIs implementiert, die als universelle Gerätefamilie bezeichnet werden. Einige werden jedoch in Erweiterungs-SDKs implementiert, und Visual Studio erkennt nur APIs, die von der Zielgerätefamilie Ihrer App oder von Erweiterungs-SDKs implementiert werden, auf die Verwiesen wird.

Wenn Sie Kompilierungsfehler zu Namespaces oder Typen oder Membern erhalten, die nicht gefunden werden konnten, ist dies wahrscheinlich die Ursache. Öffnen Sie das Thema der API in der API-Referenzdokumentation, und navigieren Sie zum Abschnitt "Anforderungen": Sie erfahren, was die implementierungsbezogene Gerätefamilie ist. Wenn dies nicht Ihre Zielgerätefamilie ist, benötigen Sie einen Verweis auf das Erweiterungs-SDK für diese Gerätefamilie, um die API für Ihr Projekt verfügbar zu machen.

Klicken Sie auf Project>Add Reference>Windows Universal>Extensions, und wählen Sie das entsprechende Erweiterungs-SDK aus. Wenn beispielsweise die APIs, die Sie aufrufen möchten, nur in der Familie mobiler Geräte verfügbar sind und sie in Version 10.0.x.y eingeführt wurden, wählen Sie windows Mobile-Erweiterungen für die UWP aus.

Dadurch wird der Projektdatei der folgende Verweis hinzugefügt:

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

Der Name und die Versionsnummer stimmen mit den Ordnern am installierten Speicherort Ihres SDK überein. Die obigen Informationen entsprechen z. B. diesem Ordnernamen:

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

Sofern Ihre App nicht auf die Gerätefamilie abzielt, die die API implementiert, müssen Sie die ApiInformation-Klasse verwenden, um das Vorhandensein der API zu testen, bevor Sie sie aufrufen (dies wird als adaptiver Code bezeichnet). Diese Bedingung wird dann überall ausgewertet, wo Ihre App ausgeführt wird. Sie wird jedoch nur auf Geräten ausgewertet, auf denen die API vorhanden ist und daher zum Aufrufen verfügbar ist. Verwenden Sie Erweiterungs-SDKs und adaptiven Code erst, nachdem Sie überprüft haben, ob eine universelle API vorhanden ist. Einige Beispiele finden Sie im folgenden Abschnitt.

Siehe auch das App-Paketmanifest.

Maximieren der Wiederverwendung von Markup und Code

Sie werden feststellen, dass Die Umgestaltung ein wenig und/oder das Hinzufügen von adaptivem Code (siehe unten) ermöglicht Es Ihnen, das Markup und den Code zu maximieren, der in allen Gerätefamilien funktioniert. Hier sind weitere Details.

  • Dateien, die für alle Gerätefamilien gemeinsam sind, benötigen keine besondere Berücksichtigung. Diese Dateien werden von der App auf allen Gerätefamilien verwendet, auf denen sie ausgeführt wird. Dazu gehören XAML-Markupdateien, imperative Quellcodedateien und Objektdateien.
  • Es ist möglich, dass Ihre App die Gerätefamilie erkennt, auf der sie ausgeführt wird, und zu einer Ansicht navigieren, die speziell für diese Gerätefamilie entwickelt wurde. Weitere Informationen finden Sie unter Erkennen der Plattform, auf der Ihre App ausgeführt wird.
  • Eine ähnliche Technik, die Sie möglicherweise hilfreich finden, wenn keine Alternative besteht, besteht darin, eine Markupdatei oder ResourceDictionary-Datei (oder den Ordner mit der Datei) einem speziellen Namen zuzuweisen, sodass er zur Laufzeit nur dann automatisch geladen wird, wenn Ihre App auf einer bestimmten Gerätefamilie ausgeführt wird. Diese Technik wird in der Fallstudie Bookstore1 veranschaulicht.
  • Um Features zu verwenden, die nicht für alle Gerätefamilien verfügbar sind (z. B. Drucker, Scanner oder kamerataste), können Sie adaptiven Code schreiben. Weitere Informationen finden Sie im dritten Beispiel in der bedingten Kompilierung und im adaptiven Code in diesem Thema.
  • Wenn Sie sowohl Windows Phone Silverlight als auch Windows 10 unterstützen möchten, können Sie möglicherweise Quellcodedateien zwischen Projekten freigeben. So geht's: Klicken Sie in Visual Studio mit der rechten Maustaste auf das Projekt in Projektmappen-Explorer, wählen Sie "Vorhandenes Element hinzufügen", wählen Sie die freizugebenden Dateien aus, und klicken Sie dann auf "Als Link hinzufügen". Speichern Sie Ihre Quellcodedateien in einem gemeinsamen Ordner im Dateisystem, in dem die Projekte, die mit ihnen verknüpft sind, diese sehen können, und vergessen Sie nicht, sie zur Quellcodeverwaltung hinzuzufügen. Wenn Sie Ihren imperativen Quellcode so berücksichtigen können, dass die meisten, wenn nicht alle, eine Datei auf beiden Plattformen funktionieren, nicht benötigen Sie zwei Kopien davon. Sie können jede plattformspezifische Logik in der Datei in bedingte Kompilierungsdirektiven einschließen, sofern möglich, oder Laufzeitbedingungen, falls erforderlich. Weitere Informationen finden Sie im nächsten Abschnitt und C#-Präprozessordirektiven.
  • Für die Wiederverwendung auf binärer Ebene anstelle der Quellcodeebene gibt es portable Klassenbibliotheken, die die Teilmenge von .NET-APIs unterstützen, die in Windows Phone Silverlight sowie in der Teilmenge für Windows 10-Apps (.NET Core) verfügbar sind. Portable Klassenbibliothekassemblys sind binärkompatibel mit diesen .NET-Plattformen und mehr. Verwenden Sie Visual Studio, um ein Projekt zu erstellen, das auf eine portable Klassenbibliothek ausgerichtet ist. Siehe plattformübergreifende Entwicklung mit der portablen Klassenbibliothek.

Bedingte Kompilierung und adaptiver Code

Wenn Sie sowohl Windows Phone Silverlight als auch Windows 10 in einer einzigen Codedatei unterstützen möchten, können Sie dies tun. Wenn Sie in Ihrem Windows 10-Projekt auf den Projekteigenschaftenseiten suchen, sehen Sie, dass das Projekt WINDOWS_UAP als Symbol für die bedingte Kompilierung definiert. Im Allgemeinen können Sie die folgende Logik verwenden, um die bedingte Kompilierung durchzuführen.

#if WINDOWS_UAP
    // Code that you want to compile into the Windows 10/11 app.
#else
    // Code that you want to compile into the Windows Phone Silverlight app.
#endif // WINDOWS_UAP

Wenn Sie Code haben, den Sie zwischen einer Windows Phone Silverlight-App und einer Windows-Runtime 8.x-App freigegeben haben, verfügen Sie möglicherweise bereits über Quellcode mit Logik wie folgt:

#if NETFX_CORE
    // Code that you want to compile into the Windows Runtime 8.x app.
#else
    // Code that you want to compile into the Windows Phone Silverlight app.
#endif // NETFX_CORE

Wenn ja, und wenn Sie windows 10 jetzt zusätzlich unterstützen möchten, können Sie dies auch tun.

#if WINDOWS_UAP
    // Code that you want to compile into the Windows 10/11 app.
#else
#if NETFX_CORE
    // Code that you want to compile into the Windows Runtime 8.x app.
#else
    // Code that you want to compile into the Windows Phone Silverlight app.
#endif // NETFX_CORE
#endif // WINDOWS_UAP

Möglicherweise haben Sie die bedingte Kompilierung verwendet, um die Behandlung der Hardwarerücktaste auf Windows Phone zu beschränken. In Windows 10 ist das Ereignis "Zurück"-Schaltfläche ein universelles Konzept. Zurück-Schaltflächen, die in Hardware oder in software implementiert sind, lösen das BackRequested-Ereignis aus, sodass dies die zu behandelnde Schaltfläche ist.

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

...

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

Möglicherweise haben Sie die bedingte Kompilierung verwendet, um die Behandlung der Hardware-Kamerataste auf Windows Phone zu beschränken. In Windows 10 ist die Hardware-Kamerataste ein Konzept, das speziell für die Mobilgerätefamilie gilt. Da ein App-Paket auf allen Geräten ausgeführt wird, ändern wir unsere Kompilierungszeitbedingung in eine Laufzeitbedingung unter Verwendung des sogenannten adaptiven Codes. Dazu verwenden wir die ApiInformation-Klasse, um zur Laufzeit die Anwesenheit der HardwareButtons-Klasse abzufragen. HardwareButtons ist im sdk für die mobile Erweiterung definiert, daher müssen wir unserem Projekt einen Verweis auf dieses SDK hinzufügen, damit dieser Code kompiliert werden kann. Beachten Sie jedoch, dass der Handler nur auf einem Gerät ausgeführt wird, das die im SDK für mobile Erweiterung definierten Typen implementiert, und das ist die Mobilgerätefamilie. Daher ist der folgende Code nur darauf bedacht, Features zu verwenden, die vorhanden sind, obwohl er sie auf eine andere Weise als die bedingte Kompilierung erreicht.

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

Weitere Informationen finden Sie unter Erkennen der Plattform, auf der Ihre App ausgeführt wird.

Das App-Paketmanifest

Die Einstellungen in Ihrem Projekt (einschließlich der Verweise auf Erweiterungs-SDKs) bestimmen den API-Oberflächenbereich, den Ihre App aufrufen kann. Ihr App-Paketmanifest bestimmt jedoch den tatsächlichen Satz von Geräten, auf denen Ihre Kunden Ihre App aus dem Store installieren können. Weitere Informationen finden Sie in "Examples in TargetDeviceFamily".

Es lohnt sich zu wissen, wie Sie das App-Paketmanifest bearbeiten, da die folgenden Themen darüber sprechen, dass sie für verschiedene Deklarationen, Funktionen und andere Einstellungen verwendet werden, die einige Features benötigen. Sie können den App-Paketmanifest-Editor von Visual Studio verwenden, um es zu bearbeiten. Wenn die Projektmappen-Explorer nicht angezeigt wird, wählen Sie sie im Menü "Ansicht" aus. Doppelklicken Sie auf Package.appxmanifest. Dadurch wird das Manifest-Editor-Fenster geöffnet. Wählen Sie die entsprechende Registerkarte aus, um Änderungen vorzunehmen und dann die Änderungen zu speichern. Möglicherweise möchten Sie sicherstellen, dass das pm:PhoneIdentity-Element im portierten App-Manifest dem Im App-Manifest der App entspricht, die Sie portieren (ausführliche Informationen finden Sie im Thema "pm:PhoneIdentity ").

Siehe Paketmanifestschemareferenz für Windows 10.

Das nächste Thema ist die Problembehandlung.