WinUI - データバインディング(Bindings->Update)
C++ で WinUI 3 ライブラリを使う
この記事は試行錯誤の結果をまとめたもので、WinUI の正しい使い方ではないかもしれません。
下図のようにTextBox に入力した文字列をもう一方のTextBoxに反映する方法を考えます。
XAMLはこんな感じです。入力用のTextBoxと出力用の読み取り専用のTextBoxがあります。
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBox Header="String" /> <FontIcon FontFamily="Segoe MDL2 Assets" Glyph="" Margin="8"/> <TextBox IsReadOnly="True" /> </StackPanel>
データバインディングで実現するためには、文字列の変数が1つあればよいので、.idl ファイルを開き、文字列型のValueStringプロパティを宣言します。
[default_interface] runtimeclass Binding1Page : Microsoft.UI.Xaml.Controls.Page { Binding1Page(); String ValueString; }
それと同時にクラスに ValueString のセッターとゲッターを実装します。
struct Binding1Page : Binding1PageT<Binding1Page> { Binding1Page(); void ValueString(const hstring& value) { m_valueString = value; } hstring ValueString() { return m_valueString; } private: hstring m_valueString; };
次に ValueString とバインディングするようにXAMLファイルを修正します。
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBox Header="String" Text="{x:Bind ValueString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> <FontIcon FontFamily="Segoe MDL2 Assets" Glyph="" Margin="8"/> <TextBox Text="{x:Bind ValueString}" IsReadOnly="True" /> </StackPanel>
うまく動作しそうですが、ここまでのコードだと TextBox のテキストを変更する毎に ValueString のセッターは呼び出されていますが、出力用の TextBox は全然更新されません。
コードの値を画面に反映させるには、Bindings->Update(); を実行します。
ValueString のセッターの実装を値の変更があったときに Bindings->Update(); を実行するように変更すれば期待した動作になります。
void Binding1Page::ValueString(const hstring& value) { if (m_valueString != value) { m_valueString = value; Bindings->Update(); } }
データバインディングを使わない方法
今回の例であればデータバインディングを使わない方が簡単かもしれません。
- コードから TextBox にアクセスできるように x:Name 属性で名前を付けます。
- テキストが変更されたときに呼び出される TextChanged イベントのイベントハンドラを入力用の TextBox に追加します。
- TextChanged イベントが発生したら、InputTextBox のテキストを OutputTextBox にコピーします。
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBox x:Name="InputTextBox" TextChanged="InputTextBox_TextChanged" Header="String" /> <FontIcon FontFamily="Segoe MDL2 Assets" Glyph="" Margin="8"/> <TextBox x:Name="OutputTextBox" IsReadOnly="True"/> </StackPanel>
void winrt::NavigationView1::implementation::Binding1Page::InputTextBox_TextChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::TextChangedEventArgs const& e) { OutputTextBox().Text(InputTextBox().Text()); }
参考
WinUI 3 with C++ 入門 - ビリヤードが好きなプログラマー
Microsoft インターフェイス定義言語 3.0 の概要 - Windows UWP applications | Microsoft Learn