Freigeben über


Eine Windows App SDK-Migration der Beispiel-App für den UWP-Foto-Editor (C++/WinRT)

Dieses Thema ist eine Fallstudie über die C++/WinRT UWP PhotoLab-Beispiel-App, die auf das Windows App SDK migriert wird.

Wichtig

Überlegungen und Strategien zum Herangehen des Migrationsprozesses und zum Einrichten Ihrer Entwicklungsumgebung für die Migration finden Sie unter Allgemeine Migrationsstrategie.

Installieren von Tools für das Windows App SDK

Informationen zum Einrichten Ihres Entwicklungscomputers finden Sie unter Installieren von Tools für das Windows App SDK.

Wichtig

Sie finden Themen mit Versionshinweisen zusammen mit dem Thema Windows App SDK – Veröffentlichungskanäle. Es gibt Versionshinweise für jeden Kanal. Überprüfen Sie unbedingt alle Einschränkungen und bekannten Probleme in den Versionshinweisen, da sich diese möglicherweise auf die Ergebnisse auswirken, wenn Sie dieser Fallstudie folgen und/oder die migrierte Anwendung ausführen.

Erstellen eines neuen Projekts

  • Erstellen Sie in Visual Studio ein neues C++/WinRT-Projekt aus der Projektvorlage Leere App, gepackt (WinUI 3 in Desktop). Nennen Sie das Projekt PhotoEditor und deaktivieren Sie Projektmappe und Projekt im selben Verzeichnis platzieren. Sie können auf das neueste Release (keine Vorschau) des Clientbetriebssystems abzielen.

Hinweis

Wir verweisen auf die UWP-Version des Beispielprojekts (das, das Sie aus dem Repository geklont haben) als Quelllösung/Projekt. Wir verweisen auf die Windows App SDK-Version als Ziellösung/Projekt.

Die Reihenfolge, in der der Code migriert wird

MainPage ist ein wichtiger und prominenter Teil der App. Aber wenn wir mit der Migration beginnen würden, dann würden wir bald feststellen, dass MainPage eine Abhängigkeit von der DetailPage-Ansicht aufweist und DetailPage eine Abhängigkeit von dem Photo-Modell aufweist. Für diese exemplarische Vorgehensweise werden wir also diesen Ansatz verfolgen.

  • Wir beginnen mit dem Kopieren der Ressourcen-Dateien.
  • Anschließend migrieren wir das Photo-Modell.
  • Als Nächstes migrieren wir die App-Klasse (da dazu einige Mitglieder hinzugefügt werden müssen, von denen DetailPage und MainPage abhängig sind).
  • Anschließend beginnen wir mit der Migration der Ansichten, beginnend mit DetailPage.
  • Zum Schluss migrieren wir noch die Ansicht MainPage.

Wir werden ganze Quellcodedateien kopieren.

In dieser exemplarischen Vorgehensweise kopieren wir Quellcodedateien mithilfe des Datei-Explorers. Wenn Sie Dateiinhalte lieber kopieren möchten, lesen Sie den Anhang: Kopieren des Inhalts der Photo-Modelldateien am Ende dieses Themas. Dort erhalten Sie ein Beispiel dafür, wie Sie dies für Photo tun können (und sie können dann ein ähnliches Verfahren auf andere Typen im Projekt anwenden). Diese Option umfasst jedoch noch viel mehr Schritte.

Kopieren von Objektdateien

  1. Suchen Sie in Ihrem Klon des Quellprojekts im Datei-Explorer den Ordner Windows-appsample-photo-editor>PhotoEditor>Objekte. Sie finden acht Objektdateien in diesem Ordner. Wählen Sie diese acht Dateien aus, und kopieren Sie sie in die Zwischenablage.

  2. Suchen Sie nun auch in Datei-Explorer den entsprechenden Ordner im von Ihnen erstellten Zielprojekt. Der Pfad zu diesem Ordner lautet PhotoEditor>PhotoEditor>Assets. Fügen Sie die soeben kopierten Objektdateien in diesen Ordner ein, und akzeptieren Sie die Aufforderung, die sieben Dateien zu ersetzen, die bereits im Ziel vorhanden sind.

  3. Erweitern Sie in Ihrem Zielprojekt in Visual Studio im Projektmappen-Explorer den Ordner Assets. Fügen Sie diesem Ordner die vorhandene bg1.png Objektdatei hinzu, die Sie gerade eingefügt haben. Sie können mit dem Mauszeiger auf die Ressourcendateien zeigen. Für jede Datei wird eine Miniaturvorschau angezeigt, die bestätigt, dass Sie die Ressourcendateien korrekt ersetzt/hinzugefügt haben.

Migrieren des Photo-Modells

Photo ist eine Laufzeitklasse, die ein Foto darstellt. Es ist ein Modell (im Sinne von Modellen, Ansichten und Ansichtsmodellen).

Kopieren von Photo-Quellcodedateien

  1. Suchen Sie in Ihrem Klon des Quellprojekts im Datei-Explorer den Ordner Windows-appsample-photo-editor>PhotoEditor. In diesem Ordner finden Sie die drei Quellcodedateien Photo.idl, Photo.h und Photo.cpp. Diese Dateien implementieren gemeinsam die Photo-Laufzeitklasse. Wählen Sie diese drei Dateien aus, und kopieren Sie sie in die Zwischenablage.

  2. Klicken Sie mit der rechten Maustaste auf den Zielprojektknoten in Visual Studio, und klicken Sie dann auf Ordner im Datei-Explorer öffnen. Dadurch wird der Zielprojektordner im Datei-Explorer geöffnet. Fügen Sie die drei Dateien, die Sie gerade kopiert haben, in diesen Ordner ein.

  3. Vergewissern Sie sich zurück im Projektmappen-Explorer bei ausgewähltem Zielprojektknoten, dass die Option Alle Dateien anzeigen aktiviert ist. Klicken Sie mit der rechten Maustaste auf die drei soeben eingefügten Dateien, und klicken Sie anschließend auf In Projekt einschließen. Deaktivieren Sie Alle Dateien anzeigen.

  4. Im Quellprojekt in Projektmappen-Explorer sind Photo.h und .cpp unter Photo.idl geschachtelt, um anzugeben, dass sie dadurch generiert werden (davon abhängig sind). Wenn Ihnen diese Anordnung gefällt, können Sie dasselbe im Zielprojekt ausführen, indem Sie manuell \PhotoEditor\PhotoEditor\PhotoEditor\PhotoEditor.vcxproj bearbeiten (zuerst müssen Sie in Visual Studio Alle speichern). Suchen Sie nach Folgendem:

    <ClInclude Include="Photo.h" />
    

    Und ersetzen Sie es durch:

    <ClInclude Include="Photo.h">
      <DependentUpon>Photo.idl</DependentUpon>
    </ClInclude>
    

    Wiederholen Sie diesen Vorgang für Photo.cpp, und speichern und schließen Sie die Projektdatei. Wenn Sie den Fokus wieder auf Visual Studio setzen, klicken Sie auf Neu laden.

Migrieren von Photo-Quellcode

  1. Suchen Sie in Photo.idl nach dem Namespacenamen Windows.UI.Xaml (Namespace für UWP-XAML), und ändern Sie ihn in Microsoft.UI.Xaml (Namespace für WinUI XAML).

Hinweis

Das Thema Zuordnen von UWP-APIs zum Windows App SDK bietet eine Zuordnung von UWP-APIs zu ihren Windows App SDK-Entsprechungen. Die oben vorgenommene Änderung ist ein Beispiel für eine Namespace-Namenänderung, die während des Migrationsprozesses erforderlich ist.

  1. In Photo.cpp fügen Sie #include "Photo.g.cpp" unmittelbar nach #include "Photo.h" zu den vorhandenen include-Direktiven hinzu. Dies ist einer der Unterschiede zwischen Ordner und Dateinamen (C++/WinRT), die zwischen UWP- und Windows App SDK-Projekten zu beachten sind.

  2. Führen Sie die folgende Suche/Ersetzung (Groß-/Kleinschreibung und ganzes Wort berücksichtigen) im Inhalt des gesamten Quellcodes in den Dateien durch, die Sie gerade kopiert und eingefügt haben.

    • Windows::UI::Xaml =>Microsoft::UI::Xaml
  3. Kopieren Sie von pch.h im Quellprojekt die folgenden Include-Elemente, und fügen Sie sie in pch.h im Zielprojekt ein. Dies ist eine Teilmenge der Headerdateien, die im Quellprojekt enthalten sind. Dies sind nur die Header, die wir benötigen, um den bisher migrierten Code zu unterstützen.

    #include <winrt/Microsoft.UI.Xaml.Media.Imaging.h>
    #include <winrt/Windows.Storage.h>
    #include <winrt/Windows.Storage.FileProperties.h>
    #include <winrt/Windows.Storage.Streams.h>
    
  4. Bestätigen Sie jetzt, dass Sie die Ziellösung erstellen können (Führen Sie sie aber noch nicht aus).

Migrieren der App-Klasse

Für App.idl und App.xaml des Zielprojekts sind keine Änderungen erforderlich. Wir müssen jedoch App.xaml.h und App.xaml.cpp bearbeiten, um der App-Klasse einige neue Mitglieder hinzuzufügen. Wir werden dies auf eine Weise tun, die uns nach jedem Abschnitt das Erstellen ermöglicht (mit Ausnahme des letzten Abschnitts, in dem es um App:OnLaunched geht).

Bereitstellen des Hauptfensterobjekts

In diesem Schritt nehmen wir die in in Windows.UI.Xaml.Window.Current in App.Window ändern beschriebene Änderung vor.

Im Zielprojekt speichert App das Hauptfensterobjekt in seinem privaten Datenelement-window. Später im Migrationsprozess (wenn wir die Verwendung des Quellprojekts von Window.Current migrieren) ist es praktisch, wenn dieses window-Datenelement statisch ist und auch über eine Accessorfunktion verfügbar gemacht wird. Daher nehmen wir diese Änderungen als Nächstes vor.

  • Da wir window als statisch festlegen, müssen wir es in App.xaml.cpp statt über den standardmäßigen Memberinitialisierer initialisieren, den der Code derzeit verwendet. So sehen diese Änderungen in App.xaml.h und App.xaml.cpp aus:

    // App.xaml.h
    ...
    struct App : AppT<App>
    {
         ...
         static winrt::Microsoft::UI::Xaml::Window Window(){ return window; };
    
    private:
         static winrt::Microsoft::UI::Xaml::Window window;
    };
    ...
    
    // App.xaml.cpp
    ...
    winrt::Microsoft::UI::Xaml::Window App::window{ nullptr };
    ...
    

App::OnNavigationFailed

Die Photo Editor-Beispiel-App verwendet Navigationslogik, um zwischen MainPage und DetailPage zu navigieren. Weitere Informationen zu Windows App SDK-Apps, die Navigation benötigen (und die nicht), finden Sie unter Muss ich die Seitennavigation implementieren?.

Die Mitglieder, die wir in den nächsten Abschnitten migrieren, sind also alle vorhanden, um die Navigation innerhalb der App zu unterstützen.

  1. Beginnen wir mit der Migration des OnNavigationFailed-Ereignishandlers. Kopieren Sie die Deklaration und die Definition dieser Memberfunktion aus dem Quellprojekt, und fügen Sie sie in das Zielprojekt (in App.xaml.h und App.xaml.cpp) ein.

  2. Im Code haben Sie in App.xaml.h eingefügt, Windows::UI::Xaml in Microsoft::UI::Xaml zu ändern.

App::CreateRootFrame

  1. Das Quellprojekt enthält eine Hilfsfunktion namens App::CreateRootFrame. Kopieren Sie die Deklaration und die Definition dieser Hilfsfunktion aus dem Quellprojekt, und fügen Sie sie in das Zielprojekt (in App.xaml.h und App.xaml.cpp) ein.

  2. Im Code haben Sie in App.xaml.h eingefügt, Windows::UI::Xaml in Microsoft::UI::Xaml zu ändern.

  3. Ändern Sie im Code, den Sie in App.xaml.cpp eingefügt haben, die beiden Vorkommen von Window::Current() in window (dies ist der Name des Datenelements der zuvor gesehenen App-Klasse).

App::OnLaunched

Das Zielprojekt enthält bereits eine Implementierung des OnLaunched-Ereignishandlers. Der Parameter ist ein Konstantenverweis auf ein Microsoft::UI::Xaml::LaunchActivatedEventArgs, was für das Windows App SDK korrekt ist (im Gegensatz zum Quellprojekt, das Windows::ApplicationModel::Activation::LaunchActivatedEventArgs verwendet, was für UWP korrekt ist).

  • Wir müssen nur die beiden Definitionen (Quelle und Ziel) von OnLaunched zusammenführen, sodass App::OnLaunched in App.xaml.cpp im Zielprojekt wie der folgende Eintrag aussieht. Beachten Sie, dass es window verwendet (anstelle von Window::Current(), wie die UWP-Version).

    void App::OnLaunched(LaunchActivatedEventArgs const&)
    {
         window = make<MainWindow>();
    
         Frame rootFrame = CreateRootFrame();
         if (!rootFrame.Content())
         {
             rootFrame.Navigate(xaml_typename<PhotoEditor::MainPage>());
         }
    
         window.Activate();
    }
    

Durch diesen Code hängt App von MainPage ab, sodass die weitere Erstellung erst möglich ist, wenn wir DetailPage und anschließend MainPage migriert haben. Wenn wir mit dem Erstellen fortfahren können, sagen wir es.

Migrieren der DetailPage-Ansicht

DetailPage ist die Klasse, die die Foto-Editor-Seite darstellt, auf der Win2D-Effekte umgeschaltet, festgelegt und verkettet werden. Sie gelangen zur Foto-Editor-Seite, indem Sie auf MainPage eine Fotominiaturansicht auswählen. DetailPage ist eine Ansicht (im Sinne von Modellen, Ansichten und Ansichtsmodellen).

Verweisen Sie auf das Win2D NuGet-Paket

Um Code in DetailPage zu unterstützen, hat das Quellprojekt eine Abhängigkeit von Microsoft.Graphics.Win2D. Daher benötigen wir auch eine Abhängigkeit von Win2D in unserem Zielprojekt.

  • Klicken Sie in der Ziellösung in Visual Studio auf Tools>NuGet-Paket-Manager>NuGet-Pakete für Projektmappe verwalten …>Durchsuchen. Vergewissern Sie sich, dass Vorabversion einbeziehen deaktiviert ist, und geben Sie Microsoft.Graphics.Win2D in das Suchfeld ein, oder fügen Sie es ein. Wählen Sie das richtige Element in den Suchergebnissen aus, überprüfen Sie das PhotoEditor-Projekt, und klicken Sie auf Installieren, um das Paket zu installieren.

Kopieren von DetailPage-Quellcodedateien

  1. Suchen Sie in Ihrem Klon des Quellprojekts im Datei-Explorer den Ordner Windows-appsample-photo-editor>PhotoEditor. In diesem Ordner finden Sie die vier Quellcodedateien DetailPage.idl, DetailPage.xaml, DetailPage.h und DetailPage.cpp. Diese Dateien implementieren die DetailPage-Ansicht. Wählen Sie diese vier Dateien aus, und kopieren Sie sie in die Zwischenablage.

  2. Klicken Sie mit der rechten Maustaste auf den Zielprojektknoten in Visual Studio, und klicken Sie dann auf Ordner im Datei-Explorer öffnen. Dadurch wird der Zielprojektordner im Datei-Explorer geöffnet. Fügen Sie die vier Dateien, die Sie gerade kopiert haben, in diesen Ordner ein.

  3. Ändern Sie in File Explorer die Namen von DetailPage.h und DetailPage.cpp jeweils in DetailPage.xaml.h und DetailPage.xaml.cpp. Dies ist einer der Unterschiede zwischen Ordner und Dateinamen (C++/WinRT), die zwischen UWP- und Windows App SDK-Projekten zu beachten sind.

  4. Vergewissern Sie sich zurück im Projektmappen-Explorer bei ausgewähltem Zielprojektknoten, dass die Option Alle Dateien anzeigen aktiviert ist. Klicken Sie mit der rechten Maustaste auf die vier Dateien, die Sie gerade eingefügt (und umbenannt) haben, und klicken Sie auf Zu Projekt hinzufügen. Deaktivieren Sie Alle Dateien anzeigen.

  5. Im Quellprojekt im Projektmappen-Explorer ist DetailPage.idl unter DetailPage.xaml geschachtelt. Wenn Ihnen diese Anordnung gefällt, können Sie dasselbe im Zielprojekt ausführen, indem Sie manuell \PhotoEditor\PhotoEditor\PhotoEditor\PhotoEditor.vcxproj bearbeiten (zuerst müssen Sie in Visual Studio Alle speichern). Suchen Sie nach Folgendem:

    <Midl Include="DetailPage.idl" />
    

    Und ersetzen Sie es durch:

    <Midl Include="DetailPage.idl">
      <DependentUpon>DetailPage.xaml</DependentUpon>
    </Midl>
    

Speichere und schließe die Projektdatei. Wenn Sie den Fokus wieder auf Visual Studio setzen, klicken Sie auf Neu laden.

Migrieren des DetailPage-Quellcodes

  1. Suchen Sie in DetailPage.idl nach Windows.UI.Xaml und ändern Sie dies in Microsoft.UI.Xaml.

  2. Ändern Sie in DetailPage.xaml.cpp den Eintrag #include "DetailPage.h" in #include "DetailPage.xaml.h".

  3. Fügen Sie direkt darunter #include "DetailPage.g.cpp" hinzu.

  4. Fügen Sie für den Aufruf der zu kompilierenden statischen App::Window-Methode (die wir hinzufügen möchten) in DetailPage.xaml.cpp#include "App.xaml.h" unmittelbar vor #include "Photo.h" hinzu.

  5. Führen Sie die folgende Suche/Ersetzungen (Groß-/Kleinschreibung und ganzes Wort berücksichtigen) im Inhalt des Quellcodes in den Dateien durch, die Sie gerade kopiert und eingefügt haben.

    • In DetailPage.xaml.h und .xaml.cpp, Windows::UI::Composition =>Microsoft::UI::Composition
    • In DetailPage.xaml.h und .xaml.cpp, Windows::UI::Xaml =>Microsoft::UI::Xaml
    • In DetailPage.xaml.cpp, Window::Current() =>App::Window()
  6. Kopieren Sie von pch.h im Quellprojekt die folgenden Include-Elemente, und fügen Sie sie in pch.h im Zielprojekt ein.

    #include <winrt/Windows.Graphics.Effects.h>
    #include <winrt/Microsoft.Graphics.Canvas.Effects.h>
    #include <winrt/Microsoft.Graphics.Canvas.UI.Xaml.h>
    #include <winrt/Microsoft.UI.Composition.h>
    #include <winrt/Microsoft.UI.Xaml.Input.h>
    #include <winrt/Windows.Graphics.Imaging.h>
    #include <winrt/Windows.Storage.Pickers.h>
    
  7. Fügen Sie außerdem oben in pch.h unmittelbar nach #pragma once Folgendes hinzu:

    // This is required because we are using std::min and std::max, otherwise 
    // we have a collision with min and max macros being defined elsewhere.
    #define NOMINMAX
    

Wir können mit dem Erstellen noch nicht beginnen, das können wir jedoch nach der Migration von MainPage (was als Nächstes kommt).

Migrieren der MainPage-Ansicht

Die Hauptseite der App ist die Ansicht, die beim Ausführen der App zuerst angezeigt wird. Diese Seite lädt die Fotos aus der Bildbibliothek und zeigt eine gekachelte Miniaturansicht an.

Kopieren von MainPage-Quellcodedateien

  1. Kopieren Sie ähnlich wie bei DetailPage nun MainPage.idl, MainPage.xaml, MainPage.h und MainPage.cpp.

  2. Benennen Sie die .h- und .cpp-Dateien jeweils in .xaml.h und .xaml.cpp um.

  3. Fügen Sie alle vier Dateien wie zuvor in das Zielprojekt ein.

  4. Im Quellprojekt im Projektmappen-Explorer ist MainPage.idl unter MainPage.xaml geschachtelt. Wenn Ihnen diese Anordnung gefällt, können Sie dasselbe im Zielprojekt ausführen, indem Sie \PhotoEditor\PhotoEditor\PhotoEditor\PhotoEditor.vcxproj manuell bearbeiten. Suchen Sie nach Folgendem:

    <Midl Include="MainPage.idl" />
    

    Und ersetzen Sie sie durch:

    <Midl Include="MainPage.idl">
      <DependentUpon>MainPage.xaml</DependentUpon>
    </Midl>
    

Migrieren von MainPage-Quellcode

  1. Suchen Sie in MainPage.idl nach Windows.UI.Xaml, und ändern Sie beide Vorkommen in Microsoft.UI.Xaml.

  2. Ändern Sie in MainPage.xaml.cpp den Eintrag #include "MainPage.h" in #include "MainPage.xaml.h".

  3. Fügen Sie direkt darunter #include "MainPage.g.cpp" hinzu.

  4. Fügen Sie für den Aufruf der zu kompilierenden statischen App::Window-Methode (die wir hinzufügen möchten) in MainPage.xaml.cpp#include "App.xaml.h" unmittelbar vor #include "Photo.h" hinzu.

Im nächsten Schritt nehmen wir die in ContentDialog und Popup erläuterte Änderung vor.

  1. Fügen Sie also in MainPage.xaml.cpp in der MainPage::GetItemsAsync-Methode unmittelbar nach der Zeile ContentDialog unsupportedFilesDialog{}; diese Codezeile hinzu.

    unsupportedFilesDialog.XamlRoot(this->Content().XamlRoot());
    
  2. Führen Sie die folgende Suche/Ersetzungen (Groß-/Kleinschreibung und ganzes Wort berücksichtigen) im Inhalt des Quellcodes in den Dateien durch, die Sie gerade kopiert und eingefügt haben.

    • In MainPage.xaml.h und .xaml.cpp, Windows::UI::Composition =>Microsoft::UI::Composition
    • In MainPage.xaml.h und .xaml.cpp, Windows::UI::Xaml =>Microsoft::UI::Xaml
    • In MainPage.xaml.cpp, Window::Current() =>App::Window()
  3. Kopieren Sie von pch.h im Quellprojekt die folgenden Include-Elemente, und fügen Sie sie in pch.h im Zielprojekt ein.

    #include <winrt/Microsoft.UI.Xaml.Hosting.h>
    #include <winrt/Microsoft.UI.Xaml.Media.Animation.h>
    #include <winrt/Windows.Storage.Search.h>
    

Vergewissern Sie sich, dass Sie die Ziellösung erstellen können (Führen Sie sie aber noch nicht aus).

MainWindow aktualisieren

  1. Löschen Sie in MainWindow.xaml den StackPanel und dessen Inhalt, da wir in MainWindow keine Benutzeroberfläche benötigen. Dadurch bleibt nur das leere Window-Element übrig.

  2. Löschen Sie in MainWindow.idl den Platzhalter Int32 MyProperty;, und belassen Sie nur der Konstruktor.

  3. Löschen Sie in MainWindow.xaml.h und MainWindow.xaml.cpp die Deklarationen und Definitionen des Platzhalters MyProperty und myButton_Click, und belassen Sie nur der Konstruktor.

Migrationsänderungen, die für Threadingmodellunterschiede erforderlich sind

Die beiden Änderungen in diesem Abschnitt sind aufgrund eines Threadingmodellunterschieds zwischen UWP und dem Windows App SDK erforderlich, wie in ASTA zu STA-Threadingmodell beschrieben. Hier finden Sie kurze Beschreibungen der Ursachen der Probleme und dann eine Möglichkeit, die einzelnen Probleme zu beheben.

MainPage

MainPage lädt Bilddateien von Ihrem Bilder-Ordner, ruft StorageItemContentProperties.GetImagePropertiesAsync auf, um die Eigenschaften der Bilddatei abzurufen, erstellt ein Photo-Modellobjekt für jede Bilddatei (speichern die gleichen Eigenschaften in einem Datenelement), und fügt dieses Photo-Objekt einer Sammlung hinzu. Die Sammlung von Photo-Objekten ist datengebunden an eine GridView-Ansicht in der Benutzeroberfläche. Im Namen dieser GridView verarbeitet MainPage das ContainerContentChanging -Ereignis, und für Phase 1 ruft der Handler eine Coroutine auf, die StorageFile.GetThumbnailAsync aufruft. Dieser Aufruf von GetThumbnailAsync führt dazu, dass Nachrichten übertragen werden (es wird nicht sofort zurückgegeben und führt alle Aufgaben asynchron aus), und dies führt zu einer Eintrittsinvarianz. Das Ergebnis ist, dass die Items-Sammlung von GridView geändert wird, während das Layout ausgeführt wird, und das führt zu einem Absturz.

Wenn wir den Aufruf von StorageItemContentProperties::GetImagePropertiesAsync auskommentieren, kommt es zu keinem Absturz. Die eigentliche Lösung besteht jedoch darin, den StorageFile.GetThumbnailAsync-Aufruf explizit asynchron zu machen, indem man kooperativ auf wil::resume_foreground wartet, unmittelbar bevor GetThumbnailAsync aufgerufen wird. Dies funktioniert, weil wil::resume_foreground den darauffolgenden Code als Aufgabe im DispatcherQueue einplant.

Dies ist der zu ändernde Code:

// MainPage.xaml.cpp
IAsyncAction MainPage::OnContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
    ...
    if (args.Phase() == 1)
    {
        ...
        try
        {
            co_await wil::resume_foreground(this->DispatcherQueue());
            auto thumbnail = co_await impleType->GetImageThumbnailAsync(this->DispatcherQueue());
            image.Source(thumbnail);
        }
        ...
    }
}

Foto

Die Photo::ImageTitle-Eigenschaft ist datengebunden an die Benutzeroberfläche, sodass die Benutzeroberfläche die Accessorfunktion für diese Eigenschaft aufruft, wenn sie deren Wert benötigt. Wenn wir jedoch versuchen, von dieser Accessorfunktion im UI-Thread auf ImageProperties.Title zuzugreifen, wird eine Zugriffsverletzung angezeigt.

Stattdessen können wir einmal über den Konstruktor von Photo auf diesen Titel zugreifen und ihn im m_imageName-Datenelement speichern, wenn es nicht leer ist. Anschließend müssen wir in der Photo::ImageTitle-Accessorfunktion nur auf das Datenelement m_imageName zugreifen.

Dies ist der zu ändernde Code:

// Photo.h
...
Photo(Photo(Windows::Storage::FileProperties::ImageProperties const& props,
    ...
    ) : ...
{
    if (m_imageProperties.Title() != L"")
    {
        m_imageName = m_imageProperties.Title();
    }
}
...
hstring ImageTitle() const
{
    return m_imageName;
}
...

Dies sind die letzten Änderungen, die wir vornehmen müssen, um die Photo-Editor-Beispiel-App zu migrieren. Im Abschnitt Testen der migrierten App bestätigen wir, dass wir die Schritte ordnungsgemäß ausgeführt haben.

Bekannte Probleme

Problem des App-Typs (betrifft nur Vorschau 3)

Wenn Sie die Schritte für diese Fallstudie mit der Projektvorlage aus der VSIX für Windows App SDK Version 1.0 Vorschau 3 ausgeführt haben, müssen Sie eine kleine Korrektur an PhotoEditor.vcxproj vornehmen. Hierzu gehst du wie folgt vor.

Klicken Sie in Visual Studio im Solution Explorer mit der rechten Maustaste auf den Projektknoten und anschließend auf Projekt entladen. Jetzt ist PhotoEditor.vcxproj zur Bearbeitung geöffnet. Fügen Sie als erstes untergeordnetes Element des Projekts ein PropertyGroup-Element wie das folgende hinzu:

<Project ... >
    <PropertyGroup>
        <EnableWin32Codegen>true</EnableWin32Codegen>
    </PropertyGroup>
    <Import ... />
...

Speichern und schließen Sie PhotoEditor.vcxproj. Klicken Sie mit der rechten Maustaste auf den Projektknoten, und klicken Sie dann auf Projekt erneut laden. Erstellen Sie das Projekt jetzt neu.

Testen der migrierten App

Erstellen Sie nun das Projekt und führen Sie die Anwendung aus, um sie zu testen. Wählen Sie ein Bild aus, legen Sie einen Zoomfaktor fest, wählen Sie Effekte aus und konfigurieren Sie sie.

Anhang: Kopieren des Inhalts der Photo-Modelldateien

Wie bereits erwähnt, haben Sie die Möglichkeit, die Quellcodedateien selbst oder den Inhalt der Quellcodedateien zu kopieren. Wir haben bereits gezeigt, wie Sie Quellcodedateien kopieren. Dieser Abschnitt enthält ein Beispiel für das Kopieren von Dateiinhalten.

Suchen Sie im Quellprojekt in Visual Studio den Ordner PhotoEditor (Universal Windows)>Modelle. Dieser Ordner enthält die Dateien Photo.idl, Photo.h und Photo.cpp, die gemeinsam die Photo-Laufzeitklasse implementieren.

Hinzufügen der IDL und Generieren von Stubs

Fügen Sie in Ihrem Zielprojekt in Visual Studio dem Projekt ein neues Midl File (.idl)-Element hinzu. Benennen Sie das neue Element Photo.idl. Löschen Sie den Standardinhalt von Photo.idl.

Kopieren Sie aus dem Quellprojekt in Visual Studio den Inhalt von Modelle>Photo.idl, und fügen Sie ihn in die Photo.idl-Datei ein, die Sie soeben dem Zielprojekt hinzugefügt haben. Suchen Sie in dem eingefügten Code nach Windows.UI.Xaml und ändern Sie dies in Microsoft.UI.Xaml.

Speichern Sie die Datei .

Wichtig

Wir sind dabei, einen Build Ihrer Ziellösung durchzuführen. Der Build wird zu diesem Zeitpunkt noch nicht abgeschlossen, aber so weit ausgeführt, um erforderliche Aufgaben auszuführen.

Erstellen Sie nun die Ziellösung. Obwohl der Build nicht abgeschlossen wird, ist dieser Prozess erforderlich, um die Quellcodedateien (Stubs) zu generieren, die wir für die Implementierung des Photo-Modells benötigen.

Klicken Sie mit der rechten Maustaste auf den Zielprojektknoten in Visual Studio, und klicken Sie dann auf Ordner im Datei-Explorer öffnen. Dadurch wird der Zielprojektordner im Datei-Explorer geöffnet. Navigieren Sie dort zum Generated Files\sources-Ordner (sodass Sie sich in \PhotoEditor\PhotoEditor\PhotoEditor\Generated Files\sources befinden). Kopieren Sie die Stubdateien Photo.h und .cpp, und fügen Sie sie in den Projektordner ein, der sich jetzt zwei Ordnerebenen höher unter \PhotoEditor\PhotoEditor\PhotoEditor befindet.

Vergewissern Sie sich zurück im Projektmappen-Explorer bei ausgewähltem Zielprojektknoten, dass die Option Alle Dateien anzeigen aktiviert ist. Klicken Sie mit der rechten Maustaste auf die soeben eingefügten Stubdateien (Photo.h und .cpp), und klicken Sie dann auf Zu Projekt hinzufügen. Deaktivieren Sie Alle Dateien anzeigen.

Eine static_assert wird am Anfang des Inhalts von Photo.h und .cpp angezeigt, die Sie löschen müssen.

Vergewissern Sie sich, dass Sie den Buildvorgang erneut ausführen können. (Führen Sie ihn aber noch nicht aus.)

Migrieren von Code in die Stubs

Kopieren Sie den Inhalt von Photo.h und .cpp vom Quellprojekt in das Zielprojekt.

Von hier aus sind die gleichen Schritte zur Migration des kopierten Codes erforderlich wie im Abschnitt Migrieren von Photo-Quellcode angegeben.