WPF

【C#/WPF実践入門編(7)】データバインディングの基礎③~双方向バインディングの実装~

Windows Presentation Foundation (WPF) のデータバインディングにおいて、UI入力をデータに自動反映させる双方向バインディングについて学びます。

前回は「データ→UI」の単方向同期を実装しましたが、今回は「UI→データ」も含めた双方向同期の方法を習得します。

以下の方に役立つ内容となっています。

  • TextBoxなどの入力コントロールとデータを自動同期したい方
  • TwoWayバインディングの仕組みを理解したい方
  • WPFのデータバインディングを完全にマスターしたい方

TextBoxに入力された内容を自動的にデータオブジェクトに反映させるには、双方向バインディング(TwoWay)の設定が必要です。

この記事では、前回のサンプルを拡張し、社員情報の名前と職業をTextBoxで編集可能にするアプリを作成します。

前回の記事を先にご覧いただくと、データバインディングについてより理解が深まります。

【C#/WPF実践入門編(5)】データバインディングの基礎①~DataContextとは?~ Windows Presentation Foundation (WPF) の特徴的な機能の一つであるデータバインディングについて学び...
【C#/WPF実践入門編(6)】データバインディングの基礎②~INotifyPropertyChangedとは?~ Windows Presentation Foundation (WPF) のデータバインディングにおいて、データ変更時にUIを自動的...
プロ太

前回学んだINotifyPropertyChangedを基盤として、今度は「UI→データ」の同期も実現していきましょう!

MVVMパターンでも頻繁に使う重要な機能です。

演習のコード一式はGitHubに置いてあります。

動画も作成しています。

講義:双方向バインディングの仕組み

前回の課題

前回作成したアプリでは、ボタンクリックによる年齢変更は正しくUIに反映されますが、逆にUI側から直接データを編集することはできませんでした。

// TextBlock(例:名前の表示)は表示専用なので、ユーザが編集できない
<TextBlock Text="{Binding Name, StringFormat='名前: {0}'}"/>

実際のアプリでは、ユーザがフォームに入力した内容をデータオブジェクトに反映させたいケースが多々あります。

双方向バインディングとは?

双方向バインディング(Two-Way Binding)は、以下の両方向の同期を自動的に行う仕組みです。

  • データ→UI: プロパティ値の変更がUIに反映される(前回実装済み)
  • UI→データ: UI入力の変更がプロパティ値に反映される(今回実装)
プロ太

これにより、TextBoxに入力すると即座にデータオブジェクトのプロパティが更新され、他の画面部分にも変更が反映されるようになります。

双方向バインディングの実装方法

コントロールでバインディングのモードを「Mode=TwoWay」とすることで、双方向バインディングの指定を行えます。

多くのコントロールではデフォルトで適切なモードが設定されているため、明示的な指定は不要な場合もあります。

<!-- 双方向バインディングの基本形 -->
<TextBox Text="{Binding Name, Mode=TwoWay}"/>

<!-- TextBoxはデフォルトでTwoWayなので、以下でもOK -->
<TextBox Text="{Binding Name}"/>

双方向バインディングでは、いつデータを更新するかをUpdateSourceTriggerで制御できます。以下が例です。

<!-- フォーカスを失った時の更新 - パフォーマンス重視 -->
<TextBox Text="{Binding Name, UpdateSourceTrigger=LostFocus}"/>

<!-- 入力のたびに更新 - リアルタイム性重視 -->
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>

UpdateSourceTriggerには以下を指定できます。

UpdateSourceTrigger説明用途
Defaultコントロールのデフォルト動作通常はこれを使用
PropertyChangedプロパティ変更のたびに更新リアルタイム同期
LostFocusフォーカスを失った時入力完了後の更新
Explicit明示的な更新指示手動制御
プロ太

TextBoxでPropertyChangedを指定すると、1文字入力するたびにデータが更新されるため、リアルタイムな同期が実現できます。

Microsoft Learnの「Binding.UpdateSourceTrigger プロパティ」の記事も参考にしてください。

演習:TextBoxで名前と職業を編集可能にする

作成するアプリの概要

前回のアプリを拡張して、以下の機能を追加します。

  • 名前・職業をTextBoxで編集可能にする
    (双方向同期でデータを更新する)
  • 人物情報の現在の各値をテキストとして表示する
    (双方向同期でデータが更新されていることがわかるようにする)

以下の手順で作成します。

  • 手順: 入力フォーム(名前・仕事)と人物情報表示部分を追加
    (XAML)
プロ太

前回のINotifyPropertyChanged実装をそのまま活用して、双方向同期を実現します!

手順:入力フォーム(名前・仕事)と人物情報表示部分を追加
(XAML)

前回のプロジェクトのMainWindow.xamlを以下のように修正し、人物情報の「名前」、「仕事」のTextBlockをTextBoxに変更します。

加えて、人物情報のデータ表示部分も追加します。(★追加)とした箇所が新しく追加した部分です。

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel Margin="10">

        <!-- タイトル -->
        <TextBlock Text="データバインディング基礎デモ" 
                   FontSize="16" FontWeight="Bold" 
                   HorizontalAlignment="Center" Margin="0,0,0,15"/>

        <!-- 人物情報エリア -->
        <GroupBox Header="人物情報" Margin="0,0,0,10">
            <StackPanel Margin="5">
                <!-- 名前入力(★追加) -->
                <StackPanel Orientation="Horizontal" Margin="0,0,0,10">
                    <Label Content="名前:" Width="60"/>
                    <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" 
                             Width="200" Height="25"/>
                </StackPanel>
                <!-- 年齢操作 -->
                <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                    <TextBlock Text="{Binding Age, StringFormat='年齢: {0}'}"/>
                    <Button Content="-" Width="20" Height="20" Margin="10,0,5,0" Click="OnDecrementAge"/>
                    <Button Content="+" Width="20" Height="20" Margin="5,0,0,0" Click="OnIncrementAge"/>
                </StackPanel>
                <!-- 職業入力 (★追加)-->
                <StackPanel Orientation="Horizontal">
                    <Label Content="職業:" Width="60"/>
                    <TextBox Text="{Binding Job, UpdateSourceTrigger=PropertyChanged}" 
                             Width="200" Height="25"/>
                </StackPanel>
            </StackPanel>
        </GroupBox>

        <!--人物情報の現在のデータを確認するためのエリア(★追加) -->
        <GroupBox Header="人物情報(現在のデータを表示)" Margin="0,0,0,15">
            <StackPanel Margin="10">
                <TextBlock Text="{Binding Name, StringFormat=名前: {0}}" />
                <TextBlock Text="{Binding Age,  StringFormat=年齢: {0}歳}" />
                <TextBlock Text="{Binding Job,  StringFormat=職業: {0}}" />
            </StackPanel>
        </GroupBox>

        <!-- 会社情報エリア -->
        <GroupBox x:Name="CompanyGroup" Header="会社情報">
            <StackPanel Margin="5">
                <TextBlock Text="{Binding Name, StringFormat='会社名: {0}'}"/>
                <TextBlock Text="{Binding Department, StringFormat='部署: {0}'}"/>
            </StackPanel>
        </GroupBox>

    </StackPanel>
</Window>
プロ太

このXAMLの変更だけで完成です!

プロ美

今回、C#コードビハインドに修正は必要ないの?

プロ太

前回、INotifyPropertyChangedインターフェイスを実装し、Personについてはすでに双方向同期が可能になっているため、今回修正は不要です。

アプリを実行

アプリをデバッグ実行して、名前や仕事をテキストボックスから変更してみましょう。

プロ美

TextBoxに入力すると、下の表示エリアが即座に変わる!これが双方向バインディングの効果だね。

プロ太

INotifyPropertyChangedインターフェイスを一度実装しておけば、各プロパティのデータバインディングは比較的簡単ですね。

UpdateSourceTriggerをLostFocusに変更するなど、色々試してみると理解が深まると思います。

まとめ

本記事では、WPF開発における双方向データバインディングの実装について学びました。

前回学んだ「データ→UI」の単方向同期に加えて、今回は「UI→データ」も含めた双方向同期を実装しました。

名前・職業編集アプリの演習を通じて、前回実装したINotifyPropertyChangedインターフェイスを活用した双方向同期の方法を学びました。

UpdateSourceTrigger=PropertyChangedを指定することで、1文字入力するたびにデータが更新される双方向バインディングを実現できます。

UIからの入力をリアルタイムでデータに反映し、同時に他の画面要素にも即座に表示するというような機能は、実用的なWPFアプリ開発において欠かせない要素となります。

次回はコマンドの解説をします。データバインディングとあわせて、MVVMパターンの基礎となる2本柱の1つです。

プロ太

引き続き、一緒にC# WPFアプリ開発を学んでいきましょう!



ABOUT ME
プロ太
●仕事:現在は個人事業主(メンター・情報発信等)、大手IT企業で技術者・マネージャ(15年以上)、大学の外部講師、学生時代は学習塾で非常勤講師(約4年間) ●博士(工学)の学位取得 ●高校生の頃に独学で始め、プログラミング歴20年以上 ●言語:C# 、Java、C/C++、Python、JavaScript/TypeScript等 ●分野:Webアプリ、テスト自動化、生成AI、デバッガ、コード解析、ドメイン特化言語

ご依頼・ご相談について

プログラミング学習のご相談、お仕事のご依頼については、
こちらのお問い合わせページをご確認ください。