Uncategorized

【C#/WPF実践入門編(5)】データバインディングの基礎①~DataContextとは?~

Windows Presentation Foundation (WPF) の特徴的な機能の一つであるデータバインディングについて学びます。

今回は、データバインディングの基本概念とDataContextの仕組みについて理解を深めます。以下の方に役立つ内容となっています。

  • WPFのデータバインディングとは何かを知りたい方
  • DataContextの役割と仕組みを理解したい方
  • MVVMパターンに進む前の基礎を固めたい方

データバインディングは、データ(クラスのプロパティなど)とUI(コントロール)を自動的に同期させる仕組みです。

この記事では、最も基本的な「初回のみの同期」について学習します。

演習では、シンプルなデータクラスを作成し、DataContextを使ってUIと自動的に紐づけるアプリを作成します。

プロ太

WPFの中核機能であるデータバインディングについて段階的に学んでいきましょう!

データバインディングはMVVMパターンへの入口としてもとても重要な内容です。

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

YouTube動画は以下です。

講義:データバインディングの基礎

データバインディングとは

WPFのデータバインディングは、データ(クラスのプロパティ)とUI(コントロール)を自動的に紐づける仕組みです。

プロ太

従来の方法では、データが変更されるたびに手動でUIを更新する必要がありました。

データバインディングを使うことで、この作業が自動化され、コードがより保守しやすくなります。

従来の手動更新とデータバインディングの違いを見てみましょう。

従来の手動更新は以下のイメージです。

// データが変更されるたびに手動でUIを更新
nameLabel.Content = person.Name;
ageLabel.Content = person.Age.ToString();

データバインディングは以下のイメージです。

<!-- XAMLで一度設定すれば自動的に同期 -->
<Label Content="{Binding Name}"/>
<Label Content="{Binding Age}"/>

同期の種類

データバインディングの同期には以下の種類があります。

モード名データ→ UIUI→ データ主な用途特徴・メモ
OneWay×ラベルやリスト表示データの変化が自動でUIに反映
TwoWay入力欄(TextBox等)UIを編集するとデータも変わる
OneWayToSource×特殊なケースUIの値だけがデータに反映
OneTime○(※最初だけ)×初期値や静的な値初回だけ同期、その後は変化しない

よく使うのは、「OneWay」と「TwoWay」です。まずはこの2つを覚えておけば大丈夫です。以下が例です。

<!-- 既定値がOneWay -->
<Label Content="{Binding Name}" />

<!-- 既定値がTwoWay ->
<TextBox Text="{Binding Name}" />

コントロールにはそれぞれ同期種類の既定値があります。例えば、表示系(例:Label)ならばOneWayユーザ入力系(例:TextBox)ならばTwoWayといった感じです。

同期の種類を変えたい場合は以下のように明示的に指定します。

<TextBox Text="{Binding Name, Mode=OneWay}" />

OneWay・TwoWayではデータ更新時にUIへ自動で反映させるためには、INotifyPropertyChangedを実装する必要があります。

INotifyPropertyChangedについては次回に詳しく扱います。今回の演習では、OneWayにおける簡単な初回のデータ同期のみ扱います。

データバインディングに必要な要素

WPFでデータバインディングを行うには、以下の要素が必要です。

  1. バインディングターゲット:データを表示するUIコントロール
  2. データソース:バインドするデータ(クラスのプロパティなど)
  3. DataContext:データソースとUIを仲介する仕組み
  4. バインディング式:XAMLで{Binding プロパティ名}として記述

全体としては以下の図のようなイメージです。

DataContextは、各UIコントロールが持つプロパティで、「このコントロールはどのデータオブジェクトを参照するか」を指定します。以下の特徴があります。

  • 親コントロールのDataContextは子コントロールへ自動的に伝搬
  • 子コントロールで独自にDataContextを設定すると、そちらを優先

また、DataContextは以下の方法で設定できます。

  • XAMLで設定DataContext="{データオブジェクト}"
  • C#コードで設定this.DataContext = データオブジェクト;
プロ太

DataContextの引き継ぎにより、親で一度設定すれば、子コントロール全体でそのデータを使えるようになります。

これにより、効率的にデータバインディングを行うことができます。

データバインディングについて、詳しくはMicrosoft Learnの「データ バインディングの概要」も参考にしてください。

演習:DataContextを使った基本的なデータバインディング

作成するアプリの概要

DataContextの基本的な使い方を学ぶため、以下の機能を持つシンプルなアプリを作成します。

  • 人物情報(名前、年齢、職業)と会社情報(名前、部署名)を表示
  • DataContextの伝搬や、別データソースの結びつけを確認できる構成

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

  • 手順1:画面作成(XAML)
  • 手順2:データクラス定義とDataContextの設定(C#コードビハインド)

データバインディングの部分を中心に解説します。

プロ太

XAML・C#コードビハインド、レイアウトを含めたコントロールの使い方の基本については、WPF実践入門編の第1~第4回を参考にしてください。

手順1:画面作成(XAML)

WPFの新規プロジェクトを作成します。作成方法はWPF実践入門編第2回の記事の手順2を参考にしてください。

MainWindow.xamlを以下のように修正します。

<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">
                <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>

ポイントは以下です。

  • GroupBox:社員情報と会社情報をグループとして分けて表示
  • {Binding プロパティ名}:データバインディング式でプロパティを指定
  • StringFormatStringFormat='名前: {0}'で表示ラベルとデータを一つの要素で表現
  • 同じプロパティ名:PersonクラスとCompanyクラスの両方に「Name」プロパティがあることで、DataContextの切り替えを確認

手順2:データクラス定義とDataContextの設定(C#コードビハインド)

MainWindow.xaml.csを以下のように修正します。

データバインディング用のクラスを定義し、DataContextを設定します。

using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            // データオブジェクトを作成
            var person = new Person
            {
                Name = "田中太郎",
                Age = 30,
                Job = "ソフトウェアエンジニア"
            };

            var company = new Company
            {
                Name = "株式会社サンプル",
                Department = "開発部"
            };

            // 1. Window全体にPersonを設定
            this.DataContext = person;
            // → この時点で、すべての子コントロールがPersonを参照

            // 2. 特定のコントロールに別のデータを設定
            CompanyGroup.DataContext = company;
            // → CompanyGroup内のコントロールだけがCompanyを参照
            // → 他の部分は引き続きPersonを参照
        }
    }

    // データクラス
    public class Person
    {
        public required string Name { get; set; }
        public required int Age { get; set; }
        public required string Job { get; set; }
    }

    public class Company
    {
        public required string Name { get; set; }
        public required string Department { get; set; }
    }
}

ポイントは以下です。

  • Window全体のDataContext設定this.DataContext = person;でWindow全体(MainWindow)のデータソースを設定
  • DataContextの伝搬:人物情報エリアはWindowのDataContextが自動で伝搬
  • 独自DataContext設定CompanyGroup.DataContext = company;で特定の部分だけ異なるデータソースを設定

アプリを実行

アプリをデバッグ実行してみましょう。

プロ美

人物情報、会社情報がそれぞれDataContextで結びつけた通りにきちんと表示されているね!

プロ美

…でもこれ、アプリ起動後にperson.Name = “新しい名前”と変更したときに、画面に自動で反映されるのかな?

プロ太

現状だと自動で変更は反映されません。

プロパティ変更時に自動で画面へ反映させるには、データクラスへINotifyPropertyChangedを実装する必要があるのです。

これについては次回、勉強しましょう!

まとめ

本記事では、WPFの核心機能であるデータバインディングの基礎について学びました。

データバインディングは、データ(クラスのプロパティ)とUI(コントロール)を自動的に同期させる仕組みで、従来の手動更新に比べてコードが簡潔になります。

データバインディングの主な特徴と利点は以下の通りです。

  • 自動同期:データとUIが{Binding}式により自動的に連携し、手動でのUI更新が不要になる
  • 柔軟な同期モード:OneWay(データ→UI)、TwoWay(双方向)など、用途に応じた同期方式を選択可能
  • DataContextの活用:親から子への自動伝搬により、効率的なデータソース管理を実現

WPFではDataContextプロパティを使うことでデータバインディングが実現できます。

PersonクラスとCompanyクラスを使った演習を通じて、DataContextの設定方法と伝搬の仕組みを実際のアプリで確認しました。

Window全体と特定のコントロールで異なるDataContextを設定することで、複数のデータソースを効率的に管理する方法も理解できました。

今回は初回同期のみでしたが、次回はINotifyPropertyChangedを実装して、プロパティ変更時の自動UI更新について学習予定です。

プロ太

データバインディングはMVVMパターンの土台となる重要な概念です!

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

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

ご依頼・ご相談について

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