UWP PhotoLab 範例應用程式的 Windows 應用程式 SDK 移轉 (C#)。
本主題是採用 C# UWP PhotoLab 範例應用程式並將其移轉到 Windows 應用程式 SDK 的案例研究。
首先複製 UWP 範例應用的存放庫,然後在 Visual Studio 中開啟解決方案。
重要
如需處理移轉程式的考慮和策略,以及如何設定用於移轉的開發環境,請參閱整體移轉策略。 特別重要的一點是,了解從 UWP 移植到 WinUI 3 時支援的功能,以便在嘗試移轉之前確保應用程式所需的所有功能均受支援。
安裝 Windows 應用程式 SDK 的工具
若要設定您的開發電腦,請參閱安裝 Windows 應用程式 SDK 的工具 (機器翻譯)。
重要
您可以在 Windows 應用程式 SDK 發行通道主題中找到版本資訊主題。 每個通道都有版本資訊。 請務必查看這些版本資訊中的任何限制和已知問題,因為這些可能會影響本案例研究和/或執行移轉的應用程式的結果。
建立新專案
在 Visual Studio 中,從空白應用程式封包 (桌面中的 WinUI 3) 專案範本建立一個新的 C# 專案。 將專案命名為 PhotoLabWinUI,取消選取將解決方案和專案放在同一目錄中。 您可以將目標設為用戶端作業系統的最新版本 (非預覽版)。
注意
我們將引用範例專案的 UWP 版本 (您從其存放庫複製的版本) 作為來源解決方案/專案。 我們將把 Windows 應用程式 SDK 版本稱為目標解決方案/專案。
我們將移轉程式代碼的順序
MainPage 是應用程式的重要且突出的部分。 但如果我們先移轉,那麼我們很快就會意識到 MainPage 依賴 DetailPage 檢視;然後 DetailPage 依賴 ImageFileInfo 模型。 因此,在本逐步解說中,我們將採用此方法。
- 我們將首先複製資產檔案。
- 然後,我們將移轉 ImageFileInfo 模型。
- 接下來,我們將移轉 App 類別 (因為需要對 DetailPage、MainPage 和 LoadedImageBrush 所依賴的類別進行更改)。
- 然後,我們將移轉 LoadedImageBrush 類別。
- 然後,我們會先從 DetailPage 開始移轉檢視。
- 我們將藉由移轉 MainPage 檢視來完成。
複製資產檔案
在 Visual Studio 的目標專案中,在方案總管中,以滑鼠右鍵按一下 Assets 資料夾,然後新增名為
Samples
。在來源專案的複製中,在檔案總管中,找到資料夾 Windows-appsample-photo-lab>PhotoLab>Assets。 您會在該資料夾中找到七個資產檔案,以及名為 Samples 的子資料夾,其中包含範例影像。 選取這七個資產檔案和範例子資料夾,並將其複製到剪貼簿。
此外,在檔案總管中,現在會在您所建立的目標專案中找到對應的資料夾。 該資料夾的路徑是 PhotoLabWinUI>PhotoLabWinUI>Assets。 將剛剛複製的資產文件和子資料夾貼上到該資料夾中,並接受提示以替換目標中已存在的任何文件。
在 Visual Studio 中的目標專案中,在方案總管中,隨著 Assets 資料夾展開,您將在 Samples 資料夾中看到 Samples 子資料夾 (您剛剛貼上的) 的內容。 您可以將滑鼠指標懸停在資源檔案上。 每個資源檔案都會顯示縮圖預覽,確認您已正確取代/新增資源檔案。
移轉 ImageFileInfo 模型
ImageFileInfo 是表示圖像檔案 (例如照片) 的模型 (在模型、視圖和視圖模型的意義上)。
複製 ImageFileInfo 原始程式碼檔案
在來源專案的複製中,在檔案總管中,找到資料夾 Windows-appsample-photo-lab>PhotoLab。 在該資料夾中,您會找到原始程式碼檔案
ImageFileInfo.cs
;該檔案包含 ImageFileInfo 的實作。 選取該檔案,並將它複製到剪貼簿。在 Visual Studio 中,右鍵按兩下目標項目節點,然後按兩下在檔案總管中打開資料夾。 這會在檔案總管中開啟目標專案資料夾。 將您剛複製的檔案貼到該資料夾中。
移轉 ImageFileInfo 原始程式碼
- 將尋找/取代專案 (比對大小寫和整字) 放在您剛貼上的
ImageFileInfo.cs
檔案中。
- %
- %
Windows.UI.Xaml 是 UWP XAML 的命名空間;Microsoft.UI.Xaml 是 WinUI XAML 的命名空間。
注意
將 UWP API 對應到 Windows 應用程式 SDK 主題提供了 UWP API 到其 Windows 應用程式 SDK 等效項的對應。 我們上面所做的更改是移轉過程中所需的命名空間名稱更改的範例。
- 現在確認您可以建置目標解決方案 (但尚未執行)。
移轉 App 類別
- 從來源專案中的
<Application.Resources>
元素中App.xaml
,尋找下列四行。 複製它們,並將其貼到目標專案中。
<SolidColorBrush x:Key="RatingControlSelectedForeground" Color="White"/>
<!-- Window width adaptive breakpoints. -->
<x:Double x:Key="MinWindowBreakpoint">0</x:Double>
<x:Double x:Key="MediumWindowBreakpoint">641</x:Double>
<x:Double x:Key="LargeWindowBreakpoint">1008</x:Double>
注意
由於目標項目將使用與來源項目不同 (且更簡單) 的導航,因此無需從來源項目的 App.xaml.cs
。
- 在目標專案中,App 會將主視窗物件儲存在其私人欄位 m_window。 稍後在移轉過程中 (當我們移轉來源項目對 Window.Current 的使用時),如果將該私有欄位改為公共靜態屬性,將會很方便。 因此,將 m_window 欄位替換為 Window 屬性,並變更對 m_window 的引用,如下所示。
// App.xaml.cs
public partial class App : Application
{
...
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
Window = new MainWindow();
Window.Activate();
}
public static MainWindow Window { get; private set; }
}
- 稍後在移轉過程中 (當我們移轉顯示 FileSavePicker 的程式碼時),如果 App 公開主視窗的處理常式 (HWND),將會很方便。 因此,新增 WindowHandle 屬性,並在 OnLaunched 方法中初始化它,如下所示。
// App.xaml.cs
public partial class App : Application
{
...
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
Window = new MainWindow();
Window.Activate();
WindowHandle = WinRT.Interop.WindowNative.GetWindowHandle(Window);
}
public static IntPtr WindowHandle { get; private set; }
}
移轉 LoadedImageBrush 模型
LoadedImageBrush 是 XamlCompositionBrushBase 的特殊化。 PhotoLab 範例應用程式會使用 LoadedImageBrush 類別將效果套用至相片。
參考 Win2D NuGet 套件
若要支援 LoadedImageBrush 中的程式代碼,來源專案相依於 Win2D。 因此,我們也需要在目標專案中相依於 Win2D。
在 Visual Studio 的目標解決方案中,按兩下工具> NuGet 封裝管理員>管理解決方案的 NuGet 套件...。>瀏覽並輸入或貼上 Microsoft.Graphics.Win2D。 在搜尋結果中選擇正確的項,選中 PhotoLabWinUI 專案,然後按兩下安裝將封包安裝到該專案中。
複製 LoadedImageBrush 原始程式碼檔案
以您複製 LoadedImageBrush.cs
的相同方式,從來源專案複製到ImageFileInfo.cs
目標專案。
移轉 LoadedImageBrush 原始程式碼
- 將尋找/取代專案 (比對大小寫和整字) 放在您剛貼上的
LoadedImageBrush.cs
檔案中。
- %
- %
- %
Window.Current.Compositor
=>App.Window.Compositor
(請參閱 將 Windows.UI.Xaml.Window.Current 變更為 App.Window)
- 確認您可以建置目標解決方案 (但尚未執行)。
移轉 DetailPage 檢視
DetailPage 是代表相片編輯器頁面的類別,其中 Win2D 效果會切換、設定及連結在一起。 選取 MainPage 上的相片縮圖,即可進入相片編輯器頁面。 DetailPage 是一種 模型 (在模型、檢視和 ViewModel 的意義上)。
複製 DetailPage 原始碼檔案
以您在先前步驟中複製檔案的方式,將 DetailPage.xaml
和 DetailPage.xaml.cs
從來源專案複製到目標專案。
移轉 DetailPage 原始程式碼
- 將尋找/取代專案 (比對大小寫和整字) 放在您剛貼上的
DetailPage.xaml
檔案中。
- %
- 將尋找/取代專案 (比對大小寫和整字) 放在您剛貼上的
DetailPage.xaml.cs
檔案中。
- %
- %
- %
- 在下一個步驟中,我們將進行 ContentDialog 和 Popup 中說明的變更。 因此,仍然在
DetailPage.xaml.cs
中的 ShowSaveDialog 方法中,在該行之前新增此程式碼ContentDialogResult result = await saveDialog.ShowAsync();
。
if (Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
{
saveDialog.XamlRoot = this.Content.XamlRoot;
}
- 還是在
DetailPage.xaml.cs
的 OnNavigateTo 方法中,刪除下面兩行程式碼。 就這兩行;在本案例研究的後面,我們將重新引入剛剛刪除的後退按鈕功能。
...
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
AppViewBackButtonVisibility.Visible;
...
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
AppViewBackButtonVisibility.Collapsed;
...
- 對於此步驟,我們將進行 MessageDialog 和 Pickers 中說明的變更。 還是在
DetailPage.xaml.cs
的 ExportImage 方法中,在該行之前加入這行程式碼var outputFile = await fileSavePicker.PickSaveFileAsync();
。
WinRT.Interop.InitializeWithWindow.Initialize(fileSavePicker, App.WindowHandle);
MainPage 有 DetailPage 的相依性,這就是為什麼我們先移轉 DetailPage 的原因。 但 DetailPage 也依賴 MainPage,因此我們還無法建置。
移轉 MainPage 檢視
應用程式的主頁代表您執行應用程式時首先看到的檢視。 該頁面從範例應用程式內建的範例資料夾中載入照片,並顯示平鋪縮圖檢視。
複製 MainPage 原始碼檔案
以您在先前步驟中複製檔案的方式,將 MainPage.xaml
和 MainPage.xaml.cs
從來源專案複製到目標專案。
移轉 MainPage 原始程式碼
- 將尋找/取代專案 (比對大小寫和整字) 放在您剛貼上的
MainPage.xaml
檔案中。
- %
仍在
MainPage.xaml
中,尋找標記animations:ReorderGridAnimation.Duration="400"
,並刪除該標記。將尋找/取代專案 (比對大小寫和整字) 放在您剛貼上的
MainPage.xaml.cs
檔案中。
- %
- %
- 在此步驟中,我們將進行 ContentDialog 和 Popup 中說明的變更。 因此,仍然在
MainPage.xaml.cs
的 GetItemsAsync 方法中的行之前新增此程式碼ContentDialogResult resultNotUsed = await unsupportedFilesDialog.ShowAsync();
。
if (Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
{
unsupportedFilesDialog.XamlRoot = this.Content.XamlRoot;
}
- 還是在
MainPage.xaml.cs
的 OnNavigateTo 方法中,刪除下面行程式碼。
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
AppViewBackButtonVisibility.Collapsed;
稍後在本案例研究中,我們將重新引進我們剛才移除的返回按鈕功能。
- 確認您可以建置目標解決方案 (但尚未執行)。
導航到 MainPage
PhotoLab 範例應用程式使用導航邏輯最初導覽至 MainPage (然後在 MainPage 和 DetailPage 之間)。 如需 Windows 應用程式 SDK 需要瀏覽的應用程式的詳細資訊 (以及不需要瀏覽的應用程式),請參閱是否需要實作頁面導覽?。
因此,我們將進行下一個導覽的支持變更。
- 在
MainWindow.xaml
中,刪除<StackPanel>
專案,並將它取代為只有具名<Frame>
元素。 結果如下所示:
<Window ...>
<Frame x:Name="rootFrame"/>
</Window>
開啟
MainWindow.xaml.cs
,然後刪除 myButton_Click 方法。仍然在
MainWindow.xaml.cs
中,將以下程式碼行新增至建構函式中。
public sealed partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
rootFrame.Navigate(typeof(MainPage));
}
}
- 確認您可以建置目標解決方案 (但尚未執行)。
還原返回按鈕功能
- 在
DetailPage.xaml
中,根元素是 RelativePanel。 在該 RelativePanel 內緊鄰StackPanel 元素之後加入以下標記。
<AppBarButton x:Name="BackButton" Click="BackButton_Click" Margin="0,0,12,0">
<SymbolIcon Symbol="Back"/>
</AppBarButton>
- 在
DetailPage.xaml.cs
中,將下列兩行程序代碼新增至 OnNavigatedTo 方法,在指示的位置。
if (this.Frame.CanGoBack)
{
BackButton.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
}
else
{
BackButton.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
}
- 仍然在
DetailPage.xaml.cs
新增以下事件處理程式。
private void BackButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
Frame.GoBack();
}
測試已移轉的應用程式
現在生成專案,並執行應用進行測試。 選取影像、設定縮放層級、選擇效果,並加以設定。