사용자 인터페이스 마이그레이션(WinUI 3 포함)

이 항목에서는 WinUI(Windows UI 라이브러리) 3으로 마이그레이션을 포함하여 UI(사용자 인터페이스) 코드를 마이그레이션하는 방법을 보여 줍니다.

API 및/또는 기능 차이점 요약

Window.Current 속성은 App.Window로 마이그레이션됩니다. 그리고 CoreDispatcher.RunAsync 메서드는 DispatcherQueue.TryEnqueue로 마이그레이션됩니다.

MessageDialogPicker에서 창의 handle(HWND)을 설정해야 합니다.

DataTransferManager API를 사용하려면 해당 API를 창과 연결해야 합니다.

ContentDialogPopup의 경우 XamlRoot 속성을 설정해야 합니다.

시각화 상태 관리자 및 Page.Resources XAML 태그를 리팩터링해야 할 수 있습니다.

Windows 앱 SDK에서 AcrylicBrush는 항상 앱 콘텐츠의 샘플입니다.

Windows.UI.Xaml.Window.Current to App.Window 변경

이 섹션은 UWP 앱에서 Windows.UI.Xaml.Window.Current 속성을 사용하는 경우에 적용됩니다. 이 속성은 Windows 앱 SDK에서 지원되지 않으므로 이 섹션에서는 Window.Current를 사용하는 UWP 코드를 포팅하는 방법에 대해 설명합니다.

// MainPage.xaml.cs in a UWP app
var width = Window.Current.Bounds.Width;
// MainPage.xaml.cpp in a UWP app
auto width{ Window::Current().Bounds().Width };

Windows 앱 SDK 앱은 App 클래스에서 공용 정적 속성을 사용하여 현재 또는 창에 대한 고유한 개념을 추가할 수 있습니다.

// App.xaml.cs in a Windows App SDK app
public partial class App : Application
{
    ...
    public static Window Window { get { return m_window; } }
    private static Window m_window;
}
// App.xaml.h in a Windows App SDK app
...
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 };
...

그런 다음 클래스 자체 내에서 Window.Currentwindow로 쉽게 변경할 수 있습니다 . App 클래스 외부에서 다음과 같이 Window.CurrentApp.Window로 변경합니다.

// MainPage.xaml.cs in a UWP app
var width = App.Window.Bounds.Width;
// MainPage.xaml.cpp in a UWP app
#include <App.xaml.h>
auto width{ App::Window().Bounds().Width };

MessageDialog 및 선택기

UWP 앱에서 Windows.UI.Popups 또는 Windows.Storage.Pickers 네임스페이스의 특정 유형을 사용하는 경우, 이 섹션에는 해당 코드를 마이그레이션하는 데 도움이 되는 정보가 포함되어 있습니다. 아래 코드 예제에서는 MessageDialog를 사용하지만 선택기(예: FileOpenPicker, FileSavePicker, 또는 FolderPicker)를 표시하는 데 정확히 동일한 기법을 적용할 수 있습니다.

데스크톱 앱에서 수행해야 하는 단계는 CoreWindow에 의존하는 Display WinRT UI 개체에 설명되어 있습니다.

참고

새 앱의 경우 MessageDialog대신 ContentDialog 컨트롤을 사용하는 것이 좋습니다. 자세한 내용은 아래의 ContentDialog 및 Popup 섹션을 참조하세요.

다음은 MessageDialog를 표시하는 몇 가지 일반적인 UWP 코드입니다.

// In a UWP app
var showDialog = new Windows.UI.Popups.MessageDialog("Message here");
await showDialog.ShowAsync();
// In a UWP app
auto showDialog{ Windows::UI::Popups::MessageDialog(L"Message here") };
co_await showDialog.ShowAsync();

Windows 앱 SDK 앱에 해당하는 코드는 다음과 같습니다.

// MainWindow.xaml.cs in a WinUI 3 app
var showDialog = new Windows.UI.Popups.MessageDialog("Message here");
WinRT.Interop.InitializeWithWindow.Initialize(showDialog,
    WinRT.Interop.WindowNative.GetWindowHandle(this));
await showDialog.ShowAsync();
// pch.h in a WinUI 3 app
...
#include <Shobjidl.h>
#include <microsoft.ui.xaml.window.h>
#include <winrt/Windows.UI.Popups.h>
...

// MainWindow.xaml.cpp
...
auto showDialog{ Windows::UI::Popups::MessageDialog(L"Message here") };

HWND hWnd{ 0 };
this->try_as<::IWindowNative>()->get_WindowHandle(&hWnd);
showDialog.as<::IInitializeWithWindow>()->Initialize(hWnd);

co_await showDialog.ShowAsync();

DataTransferManager

UWP 앱에서 DataTransferManager.ShowShareUI 메서드를 호출하는 경우, 이 섹션에는 해당 코드를 마이그레이션하는 데 도움이 되는 정보가 포함되어 있습니다.

ShowShareUI를 호출하는 몇 가지 일반적인 UWP 코드는 다음과 같습니다.

// In a UWP app
var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.GetForCurrentView();

dataTransferManager.DataRequested += (sender, args) =>
{
    args.Request.Data.Properties.Title = "In a UWP app...";
    args.Request.Data.SetText("...display the user interface for sharing content with another app.");
    args.Request.Data.RequestedOperation =
        Windows.ApplicationModel.DataTransfer.DataPackageOperation.Copy;
};

Windows.ApplicationModel.DataTransfer.DataTransferManager.ShowShareUI();
// In a UWP app
#include <winrt/Windows.ApplicationModel.DataTransfer.h>
...
auto dataTransferManager{ Windows::ApplicationModel::DataTransfer::DataTransferManager::GetForCurrentView() };

dataTransferManager.DataRequested([](Windows::ApplicationModel::DataTransfer::DataTransferManager const& /* sender */,
    Windows::ApplicationModel::DataTransfer::DataRequestedEventArgs const& args)
    {
        args.Request().Data().Properties().Title(L"In a UWP app...");
        args.Request().Data().SetText(L"...display the user interface for sharing content with another app.");
        args.Request().Data().RequestedOperation(Windows::ApplicationModel::DataTransfer::DataPackageOperation::Copy);
    });

Windows::ApplicationModel::DataTransfer::DataTransferManager::ShowShareUI();

Windows 앱 SDK 앱에서 DataTransferManager.ShowShareUI를 사용하려면 공유 UI를 창과 연결해야 합니다. 수동으로 수행해야 합니다. 자세한 정보 및 코드 예제는 CoreWindow에 의존하는 WinRT UI 개체 표시를 참조하세요.

ContentDialog 및 Popup

UWP 앱에서 Windows.UI.Xaml.Controls.ContentDialog 또는 Windows.UI.Xaml.Controls.Primitives.Popup 클래스를 사용하고 있는 경우, 이 섹션에는 해당 코드를 마이그레이션하는 데 도움이 되는 정보가 포함되어 있습니다. 아래 코드 예제에서는 ContentDialog를 사용하지만 Popup 개체를 표시하는 데 정확히 동일한 기법을 적용할 수 있습니다.

ContentDialog를 표시하는 일반적인 UWP 코드는 다음과 같습니다.

// MainPage.xaml.cs in a UWP app
var unsupportedFilesDialog = new ContentDialog();
// Set Title, Content, etc.
await unsupportedFilesDialog.ShowAsync();
// MainPage.xaml.cpp in a UWP app
ContentDialog unsupportedFilesDialog{};
// Set Title, Content, etc.
co_await unsupportedFilesDialog.ShowAsync();

Windows 앱 SDK 앱에서 대화 상자의 XamlRoot 속성을 설정하기만 하면 됩니다. 방법은 다음과 같습니다.

// MainPage.xaml.cs in a Windows App SDK app
var unsupportedFilesDialog = new ContentDialog();
// Set Title, Content, etc.
unsupportedFilesDialog.XamlRoot = this.Content.XamlRoot;
await unsupportedFilesDialog.ShowAsync();
// MainPage.xaml.cpp in a Windows App SDK app
ContentDialog unsupportedFilesDialog{};
// Set Title, Content, etc.
unsupportedFilesDialog.XamlRoot(this->Content().XamlRoot());
co_await unsupportedFilesDialog.ShowAsync();

페이지 탐색을 구현해야 하나요?

UWP 프로젝트에서 앱이 한 페이지에만 있는 경우에는 기본적으로 클래스의 메서드에 탐색 코드가 포함됩니다.

Visual Studio에서 새 Windows 앱 SDK 프로젝트를 만들 때 프로젝트 템플릿은 MainWindow 클래스(유형 Microsoft.UI.Xaml.Window)를 제공하지만 페이지는 없습니다. 그리고 프로젝트 템플릿은 탐색 코드를 제공하지 않습니다.

매우 간단한 Windows 앱 SDK 앱(단일 페이지 앱)의 경우 단순화할 수 있습니다. Windows 앱 SDK 프로젝트에서는 페이지나 사용자 지정 컨트롤을 만들 필요가 없지만 대신 해당 단일 페이지의 XAML 태그 및 코드 숨김을 MainWindow에 복사할 수 있습니다. 그러나 MainWindow에서 지원하지 않는 몇 가지 항목이 있습니다. 에는 DependencyObject가 없으므로 리소스DataContext와 같은 기능이 없습니다. 로드언로드와 같은 이벤트는 수행하지 않습니다. 자세한 내용 및 해결 방법은 시각적 상태 관리자 및 Page.Resources를 참조하세요.

반면에 Windows 앱 SDK 앱의 페이지 간 탐색을 원하거나 필요한 경우 UWP 앱에서 App.OnLaunchedApp::OnNavigationFailed 메서드를 마이그레이션하여 탐색할 수 있습니다. App.OnLaunched에서 탐색 코드(rootFrame을 만들고 앱의 첫 번째 페이지로 이동하는 코드)를 찾아 기존 두 줄의 코드 간에 바로 병합합니다(창을 만들고 활성화하는 줄). 복사하여 붙여넣은 코드도 마이그레이션해야 합니다. 간단한 코드 예제는 Page 클래스를 참조하세요.

시각적 상태 관리자 및 Page.Resources

페이지 탐색을 구현해야 하나요?를 참조하세요. XAML 태그 및 코드 숨김을 MainWindow로 복사할 수 있는 매우 간단한 UWP 앱이 있는 경우 이러한 예외를 염두에 두어야 합니다 .

MainWindow 클래스(Microsoft.UI.Xaml.Window 형식)는 컨트롤이 아니므로 시각적 상태 관리자 XAML 태그 및 코드 숨김이 지원되지 않습니다(자습서: 적응 레이아웃 만들기 참조). 그러나 다음과 같은 두 가지 옵션을 사용할 수 있습니다.

  • UserControl 항목을 프로젝트에 추가하고 태그 및 코드 숨김으로 마이그레이션합니다. 그런 다음 MainWindow에 해당 사용자 컨트롤의 인스턴스를 배치합니다.
  • Page 항목을 프로젝트에 추가하고 태그 및 코드 숨김으로 마이그레이션합니다. 그런 다음 페이지 탐색을 구현해야 하나요?에 설명된 대로 클래스에 코드를 추가하여 시작 시 해당 페이지로 이동합니다.

또한 <Page.Resources> 요소를 MainWindow에 복사할 수 없으며, 대신 이름을 <Window.Resources>로 바꿉니다. 대신 MainWindow의 XAML 태그에서 루트 레이아웃 컨테이너 (예: 그리드) 아래의 리소스 요소를 부모로 설정합니다. 다음과 같이 표시됩니다.

<Window ...>
    <Grid>
        <Grid.Resources>...</Grid.Resources>
        ...
    </Grid>
</Window>

AcrylicBrush.BackgroundSource property

AcrylicBrush.BackgroundSource 속성은 UWP에는 있지만 Windows 앱 SDK에는 없습니다. Windows 앱 SDK에서 AcrylicBrush는 항상 앱 콘텐츠의 샘플입니다.

따라서 UWP 앱의 원본 코드에서 AcrylicBrush.BackgroundSource 속성에 액세스하는 경우 (XAML 태그 또는 명령적 코드에서) 앱을 Windows 앱 SDK로 마이그레이션할 때 해당 코드를 제거합니다.