Na aula anterior, adicionamos um botão no XAML e geramos um evento associado. A primeira funcionalidade implementada alterava o texto do botão ao clicar nele.
Primeiro, volte ao arquivo XAML. Precisamos nomear o botão com x:Name="btnAdd" para manipulá-lo no código C++ do back-end.
<Grid>
<Button x:Name="btnAdd" Content="Click Me" HorizontalAlignment="Center" VerticalAlignment="Center" Click="OnButtonClick"/>
</Grid>Code language: HTML, XML (xml)
Em seguida, acesse a função de implementação OnButtonClick dentro de MainWindow.xaml.cpp.

Podemos obter diretamente o objeto botão por meio da variável btnAdd declarada acima.
Ao clicar, definimos sua propriedade Content como “Welcome to FoxDevelop.com”.
Vamos executar o projeto para testar o funcionamento.

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)
Como podemos ver, o clique consegue modificar propriedades da interface. Em seguida, criaremos uma propriedade inteira para contar cliques, incrementando seu valor cada vez que o botão for pressionado. Essa propriedade será vinculada a um TextBlock no XAML para que a interface seja atualizada automaticamente com o valor mais recente.
Vinculação de Propriedades
Para evitar interferências de códigos de exemplos anteriores, você pode criar um novo projeto vazio.
Siga os passos abaixo:
Modifique o XAML e adicione um 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)
Depois, no arquivo .cpp, faça com que MyProperty retorne um número.
namespace winrt::WinuiDemo::implementation
{
int32_t MainWindow::MyProperty()
{
return 100;
}
void MainWindow::MyProperty(int32_t /* value */)
{
throw hresult_not_implemented();
}
}
Code language: C++ (cpp)
Compile e execute em seguida.
Seu ambiente de desenvolvimento pode exibir o erro abaixo e o processo de compilação ficará travado indefinidamente.
Build started at 14:42...
1>------ Build started: Project: WinuiCppDemo, Configuration: Debug x64 ------
1>WindowsAppSDKMLDeploymentMode=Framework
1>MainWindow.xaml.cpp
A mensagem de erro é a seguinte:
#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)
Atualizar para C++20
O WinUI 3 e o C++/WinRT são baseados em corrotinas padronizadas, e a atualização para C++20 facilita a manutenção futura.
Acesse Propriedades do Projeto → C/C++ → Linguagem → Padrão de Linguagem C++ e selecione C++20.

Recompile o projeto. O processo demorará muito tempo e gerará 1,3 GB de arquivos intermediários no caminho D:\Demos\WinuiDemo\WinuiDemo\x64\Debug, explicando a lentidão. O tempo varia conforme o hardware do computador. Após compilar com sucesso, ao rodar o app, o número 100 aparecerá na tela.
int32_t MainWindow::MyProperty()
{
return 100;
}Code language: C++ (cpp)
A janela exibe diretamente o valor retornado por essa propriedade.

Implementar contador incremental ao clicar no botão
Agora adicionamos um botão e vinculamos um evento de clique a ele.
<?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)
Passe o cursor sobre Button_Click dentro de Click=”Button_Click” e pressione F12: o Visual Studio gerará automaticamente a assinatura da função de evento nos arquivos .h e .cpp.
void Button_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
A sintaxe é idêntica ao exemplo anterior. Precisamos então de uma variável membro privada do tipo int32_t para armazenar o número de cliques.
Primeiro, adicione uma propriedade inteira no arquivo MainWindow.xaml.h para guardar o valor do contador.
Propriedades definidas em arquivos .idl são apenas uma interface para acesso externo; devemos criar um campo privado próprio para armazenar os dados reais.
Ao escrever
Int32 MyPropertyno IDL, a classe expõe uma propriedade Int32 de leitura e gravação para componentes externos.O compilador gera automaticamente os métodos virtuais Get/Set e o evento de alteração de propriedade
MyPropertyChanged
int32_t m_myPropValue = 0; // Variável privada que armazena a quantidade de cliques!Code language: C++ (cpp)
#pragma once
#include "MainWindow.g.h"
namespace winrt::WinuiDemo::implementation
{
struct MainWindow : MainWindowT<MainWindow>
{
private:
int32_t m_myPropValue = 0; // Armazena o valor de MyProperty
public:
MainWindow()
{
// Objetos Xaml não devem chamar InitializeComponent no construtor.
// Veja https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent
}
//funções getter & setter
int32_t MyProperty();
void MyProperty(int32_t value);
//Função de clique
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)

Agora modifique as funções getter e setter no arquivo .cpp. No manipulador de clique, pegue o valor atual com MyProperty(), some 1 e atribua novamente. Há um ponto essencial:
this->Bindings->Update(); Não omita essa linha em hipótese alguma. Ela avisa todos os elementos de interface vinculados a essa propriedade para se atualizarem; sem ela, a tela nunca mudará os valores.
#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;
// Para saber mais sobre WinUI, estrutura de projetos e modelos: http://aka.ms/winui-project-info.
namespace winrt::WinuiDemo::implementation
{
int32_t MainWindow::MyProperty()
{
return m_myPropValue; //recupera o valor de m_myPropValue
}
void MainWindow::MyProperty(int32_t value)
{
m_myPropValue = value; //define o valor em m_myPropValue
this->Bindings->Update(); // Força a atualização de todos os x:Bind da página para atualizar a UI
}
}
void winrt::WinuiDemo::implementation::MainWindow::Button_Click(winrt::Windows::Foundation::IInspectable const& sender,
winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
MyProperty(MyProperty() + 1);//atualiza m_myPropValue, soma 1
}
Code language: C++ (cpp)

Recompile e execute o aplicativo novamente.
No meu computador, a compilação demorou muito tempo; o tempo varia conforme o hardware.
Build started at 15:29...
1>------ Build started: Project: WinuiDemo, Configuration: Debug x64 ------
1>WindowsAppSDKMLDeploymentMode=Framework
1>App.xaml.cpp
1>MainWindow.xaml.cpp
A compilação C++ gera muitos arquivos intermediários; na minha máquina o processo levou mais de dez minutos sem concluir no início.

Às 15:40 do horário local, a compilação finalmente terminou e a janela do app abriu. Todo o processo levou 11 minutos inteiros. Várias vezes achei que o programa tinha travado e quase fechei o Visual Studio.
Resultado final da execução

Esta aula termina aqui. Hoje aprendemos dois pontos principais: primeiro, executar lógica de back-end e alterar o conteúdo da interface ao clicar em um botão; segundo, o mecanismo de vinculação de propriedades, que faz a UI se atualizar automaticamente quando o valor de uma propriedade do back-end muda.