In der letzten Lektion haben wir einen Button im XAML-Code hinzugefügt und ein Klick-Ereignis erstellt. Unsere erste Funktionsimplementierung hat den Text des Buttons bei einem Klick verändert.
Zuerst wechseln wir zurück zur XAML-Datei. Dem Button geben wir den Namen x:Name="btnAdd", damit wir ihn im C++-Backend-Code ansprechen und bearbeiten können.
<Grid>
<Button x:Name="btnAdd" Content="Click Me" HorizontalAlignment="Center" VerticalAlignment="Center" Click="OnButtonClick"/>
</Grid>Code-Sprache: HTML, XML (xml)
Als Nächstes öffnen wir die Implementierungsfunktion OnButtonClick in der Datei MainWindow.xaml.cpp.

Über die zuvor definierte Variable btnAdd können wir das Button-Objekt direkt abrufen.
Bei einem Klick wird seine Content-Eigenschaft auf den Text „Welcome to FoxDevelop.com“ gesetzt.
Nun führen wir das Projekt aus, um das Ergebnis zu testen.

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-Sprache: C++ (cpp)
Man erkennt, dass Klickaktionen UI-Eigenschaften verändern können. Im nächsten Schritt erstellen wir eine Ganzzahl-Eigenschaft zum Zählen der Klicks. Bei jedem Klick erhöht sich der Wert um eins, diese Eigenschaft binden wir an ein TextBlock im XAML, damit die Benutzeroberfläche automatisch den aktuellen Zählerwert anzeigt.
Eigenschaftsbinding
Um Störungen durch alten Beispielcode zu vermeiden, empfehle ich, ein neues leeres Projekt zu erstellen.
Führen Sie die folgenden Schritte durch:
Bearbeiten Sie die XAML-Datei und fügen Sie ein TextBlock-Steuerelement hinzu.
<?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-Sprache: C++ (cpp)
In der .cpp-Datei lassen wir MyProperty einfach eine Zahl zurückgeben.
namespace winrt::WinuiDemo::implementation
{
int32_t MainWindow::MyProperty()
{
return 100;
}
void MainWindow::MyProperty(int32_t /* value */)
{
throw hresult_not_implemented();
}
}
Code-Sprache: C++ (cpp)
Kompilieren und starten Sie danach das Projekt.
Je nach Entwicklungsumgebung kann folgender Fehler auftreten und der Build-Vorgang bleibt hängen.
Build started at 14:42...
1>------ Build started: Project: WinuiCppDemo, Configuration: Debug x64 ------
1>WindowsAppSDKMLDeploymentMode=Framework
1>MainWindow.xaml.cpp
Die Fehlermeldung lautet wie folgt:
#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-Sprache: PHP (php)
Aktualisierung auf C++20
WinUI 3 und C++/WinRT basieren auf standardkonformen Coroutinen. Ein Upgrade auf C++20 vereinfacht die zukünftige Wartung deutlich.
Gehen Sie zu Projekteigenschaften → C/C++ → Sprache → C++-Sprachstandard und wählen Sie C++20 aus.

Starten Sie den Build erneut. Der Vorgang dauert extrem lange, da unter dem Pfad D:\Demos\WinuiDemo\WinuiDemo\x64\Debug Zwischendateien mit einer Gesamtgröße von 1,3 GB erzeugt werden. Die benötigte Zeit hängt von der PC-Hardware ab. Nach erfolgreicher Kompilierung wird beim Ausführen des Programms die Zahl 100 im Fenster angezeigt.
int32_t MainWindow::MyProperty()
{
return 100;
}Code-Sprache: C++ (cpp)
Das Fenster zeigt direkt den von dieser Eigenschaft zurückgegebenen Wert an.

Implementierung eines klickgesteuerten Zählers
Nun fügen wir einen Button hinzu und verknüpfen ein Klick-Ereignis damit.
<?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-Sprache: HTML, XML (xml)
Bewegen Sie den Mauszeiger auf Button_Click innerhalb von Click=“Button_Click“ und drücken Sie F12. Visual Studio erstellt automatisch die Signatur der Ereignisfunktion in der .h- und .cpp-Datei.
void Button_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
Die Schreibweise ist identisch mit dem vorherigen Beispiel. Als Nächstes benötigen wir eine private int32_t-Membervariable zum Speichern der Klickzahl.
Zuerst fügen wir in der Headerdatei MainWindow.xaml.h eine Ganzzahl-Eigenschaft hinzu, um den Zählwert abzulegen.
Eigenschaften, die in .idl-Dateien definiert werden, dienen nur als Schnittstelle für den externen Zugriff. Die eigentlichen Daten müssen wir in einer eigenen privaten Variable speichern.
Schreiben wir im IDL-Code
Int32 MyProperty, stellt die Klasse eine les- und schreibbare Int32-Eigenschaft für externe Aufrufer bereit.Der Compiler generiert automatisch virtuelle Get/Set-Methoden sowie das Ereignis zur Eigenschaftsänderung
MyPropertyChanged
int32_t m_myPropValue = 0; // Private Variable zum Speichern der Klickzahl!Code-Sprache: C++ (cpp)
#pragma once
#include "MainWindow.g.h"
namespace winrt::WinuiDemo::implementation
{
struct MainWindow : MainWindowT<MainWindow>
{
private:
int32_t m_myPropValue = 0; // Speichert den Wert von MyProperty
public:
MainWindow()
{
// Xaml-Objekte dürfen InitializeComponent nicht im Konstruktor aufrufen.
// Siehe https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent
}
//Getter & Setter Funktionen
int32_t MyProperty();
void MyProperty(int32_t value);
//Klick-Ereignis Funktion
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-Sprache: C++ (cpp)

Nun bearbeiten wir die Getter- und Setter-Funktionen in der .cpp-Datei. Innerhalb der Klickfunktion rufen wir mit MyProperty() den aktuellen Wert ab, erhöhen ihn um 1 und schreiben ihn zurück. Ein extrem wichtiger Punkt:
this->Bindings->Update(); Diese Zeile darf auf keinen Fall weggelassen werden. Sie informiert alle an diese Eigenschaft gebundenen UI-Elemente über eine Aktualisierung; ohne diese Zeile ändert sich die Anzeige im Fenster nicht.
#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;
// Mehr Informationen zu WinUI, Projektstruktur und Vorlagen: http://aka.ms/winui-project-info.
namespace winrt::WinuiDemo::implementation
{
int32_t MainWindow::MyProperty()
{
return m_myPropValue; // Wert von m_myPropValue auslesen
}
void MainWindow::MyProperty(int32_t value)
{
m_myPropValue = value; // Wert in m_myPropValue speichern
this->Bindings->Update(); // Alle x:Bind-Bindungen der Seite neu zeichnen, UI-Anzeige aktualisieren
}
}
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 aktualisieren, um 1 erhöhen
}
Code-Sprache: C++ (cpp)

Kompilieren und führen Sie das Projekt erneut aus.
Auf meinem Rechner dauert der Build extrem lange, die Dauer hängt von der Hardwareausstattung ab.
Build started at 15:29...
1>------ Build started: Project: WinuiDemo, Configuration: Debug x64 ------
1>WindowsAppSDKMLDeploymentMode=Framework
1>App.xaml.cpp
1>MainWindow.xaml.cpp
Der C++-Kompiliervorgang erzeugt zahlreiche Zwischendateien, bei mir lief der Build über zehn Minuten ohne Abschluss.

Um 15:40 Uhr Ortszeit war der Build endlich abgeschlossen und das Programmfenster öffnete sich – der gesamte Vorgang dauerte ganze 11 Minuten. Mehrmals dachte ich, der Prozess sei abgestürzt und wollte Visual Studio schließen.
Ergebnis der fertigen Anwendung

Damit endet diese Lektion. Heute haben wir zwei Kernpunkte gelernt: Erstens, wie man bei einem Button-Klick Backend-Logik ausführt und den Fensterinhalt ändert; zweitens das Prinzip des Eigenschaftsbindings, bei dem die Benutzeroberfläche automatisch aktualisiert wird, sobald sich der Wert einer Backend-Eigenschaft ändert.