지난 수업에서 XAML에 버튼을 추가하고 이벤트를 생성했습니다. 먼저 구현한 기능은 버튼을 클릭하면 버튼 텍스트가 변경되는 로직입니다.
먼저 XAML 파일로 돌아와 버튼에 x:Name="btnAdd" 이름을 지정합니다. 이렇게 하면 백엔드 C++ 코드에서 해당 버튼 객체를 조작할 수 있습니다.
<Grid>
<Button x:Name="btnAdd" Content="Click Me" HorizontalAlignment="Center" VerticalAlignment="Center" Click="OnButtonClick"/>
</Grid>Code language: HTML, XML (xml)
그 다음 MainWindow.xaml.cpp 안의 OnButtonClick 구현 함수로 이동합니다.

위에서 선언한 btnAdd를 통해 버튼 객체를 직접 가져올 수 있습니다.
클릭 시 Content 속성을 “Welcome to FoxDevelop.com”으로 변경합니다.
이제 프로젝트를 실행해 확인합니다.

void winrt::WinuiCppDemo::implementation::MainWindow::OnButtonClick(winrt::Windows::Foundation::IInspectable const& sender,
winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
btnAdd().Content(box_value(L"Welcome to FoxDevelop.com"));
}
Code language: C++ (cpp)
클릭으로 UI 속성을 수정할 수 있는 것을 확인했습니다. 다음으로 클릭 횟수를 기록하는 정수 속성을 만들어 클릭할 때마다 값을 1씩 증가시키고, 이 속성을 XAML의 텍스트블록에 바인딩해 UI가 자동으로 최신 값을 표시하도록 구현합니다.
속성 바인딩
이전 예제 코드의 간섭을 피하려면 빈 새 프로젝트를 생성해서 실습하는 것을 권장합니다.
아래 단계대로 진행합니다.
XAML을 수정하고 TextBlock을 추가합니다.
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="WinuiDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinuiDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="WinuiDemo">
<Grid>
<TextBlock Text="{x:Bind MyProperty}" FontSize="24"/>
</Grid>
</Window>
Code language: C++ (cpp)
그 다음 .cpp 파일에서 MyProperty가 숫자를 반환하도록 작성합니다.
namespace winrt::WinuiDemo::implementation
{
int32_t MainWindow::MyProperty()
{
return 100;
}
void MainWindow::MyProperty(int32_t /* value */)
{
throw hresult_not_implemented();
}
}
Code language: C++ (cpp)
빌드 후 실행합니다.
개발 환경에 따라 아래 오류가 발생하고 빌드 프로세스가 멈춰버릴 수 있습니다.
Build started at 14:42...
1>------ Build started: Project: WinuiCppDemo, Configuration: Debug x64 ------
1>WindowsAppSDKMLDeploymentMode=Framework
1>MainWindow.xaml.cpp
오류 내용은 다음과 같습니다.
#error directive: "C++/WinRT no longer supports pre-standardization coroutines.
If you use co_await, switch to /await:strict or upgrade to C++20. If you do not,
remove /await from the compiler flags."Code language: PHP (php)
C++20으로 업그레이드
WinUI 3와 C++/WinRT는 표준 코루틴 기반으로 제작되었으며 C++20으로 업그레이드하면 유지보수가 훨씬 수월해집니다.
프로젝트 속성 → C/C++ → 언어 → C++ 언어 표준 메뉴에서 C++20을 선택합니다.

다시 빌드를 실행합니다. 빌드 시간이 매우 오래 걸리며 D:\Demos\WinuiDemo\WinuiDemo\x64\Debug 경로에 1.3GB 크기의 중간 파일들이 생성됩니다. PC 사양에 따라 소요 시간은 달라집니다. 빌드 성공 후 앱을 실행하면 화면에 숫자 100이 표시됩니다.
int32_t MainWindow::MyProperty()
{
return 100;
}Code language: C++ (cpp)
화면에는 이 속성이 반환하는 값이 출력됩니다.

버튼 클릭 카운터 증가 기능 구현
이제 버튼을 추가하고 클릭 이벤트를 연결합니다.
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="WinuiDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinuiDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="WinuiDemo">
<StackPanel Orientation="Vertical">
<TextBlock Text="{x:Bind MyProperty}" FontSize="24"/>
<Button Content="Click Me" Click="Button_Click"/>
</StackPanel>
</Window>
Code language: HTML, XML (xml)
Click=”Button_Click” 안의 Button_Click 텍스트에 커서를 올리고 키보드 F12를 누르면 .h, .cpp 파일에 이벤트 함수가 자동 생성됩니다.
void Button_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
작성 방식은 앞선 예시와 동일합니다. 다음으로 클릭 횟수를 저장할 int32_t 타입의 비공개 멤버 변수를 선언합니다.
먼저 MainWindow.xaml.h 헤더 파일에 카운트 값을 저장할 정수 속성을 추가합니다.
.idl 파일에 작성한 속성은 외부 접근용 인터페이스일 뿐 실제 데이터를 저장하는 필드는 직접 선언해야 합니다.
IDL에
Int32 MyProperty를 작성하면 클래스 외부에 읽기/쓰기 가능한 Int32 속성이 노출됩니다.컴파일러가 자동으로 Get/Set 가상 함수와 속성 변경 이벤트
MyPropertyChanged를 생성합니다.
int32_t m_myPropValue = 0; // 비공개 변수, 클릭 횟수 저장!Code language: C++ (cpp)
#pragma once
#include "MainWindow.g.h"
namespace winrt::WinuiDemo::implementation
{
struct MainWindow : MainWindowT<MainWindow>
{
private:
int32_t m_myPropValue = 0; // MyProperty 값 저장
public:
MainWindow()
{
// Xaml 객체는 생성자 내에서 InitializeComponent를 호출하면 안 됩니다.
// 참고: https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent
}
//getter & setter 함수
int32_t MyProperty();
void MyProperty(int32_t value);
//클릭 이벤트 함수
void Button_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
};
}
namespace winrt::WinuiDemo::factory_implementation
{
struct MainWindow : MainWindowT<MainWindow, implementation::MainWindow>
{
};
}
Code language: C++ (cpp)

이제 .cpp 파일의 속성 읽기/쓰기 함수를 수정합니다. 클릭 이벤트 안에서 MyProperty()로 현재 값을 가져온 뒤 1을 더해 다시 할당합니다. 가장 중요한 한 가지가 있습니다.
this->Bindings->Update(); 이 코드는 절대 빼먹으면 안 됩니다. 이 코드가 해당 속성에 바인딩된 모든 UI 요소에 새로고침을 알려주며, 누락하면 화면 값이 갱신되지 않습니다.
#include "pch.h"
#include "MainWindow.xaml.h"
#if __has_include("MainWindow.g.cpp")
#include "MainWindow.g.cpp"
#endif
using namespace winrt;
using namespace Microsoft::UI::Xaml;
// WinUI, WinUI 프로젝트 구조 및 템플릿에 대한 자세한 정보: http://aka.ms/winui-project-info.
namespace winrt::WinuiDemo::implementation
{
int32_t MainWindow::MyProperty()
{
return m_myPropValue; //m_myPropValue 값 반환
}
void MainWindow::MyProperty(int32_t value)
{
m_myPropValue = value; //m_myPropValue에 값 저장
this->Bindings->Update(); // 페이지 내 모든 x:Bind 바인딩 강제 갱신, UI 표시 업데이트
}
}
void winrt::WinuiDemo::implementation::MainWindow::Button_Click(winrt::Windows::Foundation::IInspectable const& sender,
winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
MyProperty(MyProperty() + 1);//m_myPropValue 값 갱신, 1 증가
}
Code language: C++ (cpp)

다시 빌드하고 실행합니다.
저자의 환경에서는 빌드 대기 시간이 매우 길었으며 PC 사양에 따라 차이가 발생합니다.
Build started at 15:29...
1>------ Build started: Project: WinuiDemo, Configuration: Debug x64 ------
1>WindowsAppSDKMLDeploymentMode=Framework
1>App.xaml.cpp
1>MainWindow.xaml.cpp
C++ 빌드 과정에서 수많은 중간 파일이 생성되며 저자 환경에서는 10분 이상 빌드가 완료되지 않았습니다.

로컬 시간 15:40에 드디어 빌드가 완료되고 앱 창이 표시되었으며 총 11분이 소요되었습니다. 중간에 프로그램이 멈춘 줄 알고 Visual Studio를 닫을 뻔했습니다.
최종 실행 결과

이번 수업은 여기까지입니다. 오늘 배운 내용은 두 가지입니다. 첫째, 버튼 클릭 후 백엔드 로직을 실행하고 화면 내용을 수정하는 방법, 둘째, 속성 바인딩으로 백엔드 값을 변경하면 UI가 자동으로 최신 상태로 갱신되는 원리입니다.