
WPFのデータバインディングとは?C#によるデータの操作方法
WPFには、UI要素とデータソースを接続する「データバインディング」という機能があります。データソースには、.NETオブジェクト / XML / ADO.NETなどの様々なデータを設定することが可能です。 データバインディングは、WPF開発おける重要な役割を担っており、必須知識ともいえるでしょう。
- SE
- WPFのデータバインディングがなかなか理解できません……
- PL
- WPFのデータバインディングは多機能な反面、最初は理解が難しいかもしれません。実際にアプリを作りながら理解していきましょう!
目次
WPFのデータバインディングの概要
データバインディングとは、アプリUI(ビュー)と、そこに表示されるモデルなどのデータソースを接続するための機能です。
例えば、TextBoxとモデル(.NETクラスなど)のプロパティをバインディングで接続しておくと、TextBoxの入力内容に変更があった時に、自動的にモデル(C#などで作られたクラス)に入力値を反映することができます。
データバインディングにおける重要な4つの要素
WPFのデータバインディングを理解する上で、次の4つの要素(用語)について知っておく必要があります。
- ◆バインディング ターゲット:データ反映先のオブジェクト(主にUI要素)
- ◆ターゲット プロパティ:データ反映先のバインディング ターゲットのプロパティ
- ◆バインディング ソース:データ提供元(.NET オブジェクト、ADO.NET、XML など)
- ◆ソース プロパティ:データ提供元のバインディング ソースのプロパティ
注意点として、「ターゲット プロパティ」には、依存関係プロパティを指定する必要があります。実際は、TextBoxのTextプロパティなど、WPFのUI要素の多くのプロパティは依存関係プロパティになっており、そこまで強く意識する必要はありません。
また、依存関係プロパティでも、読み取り専用のプロパティは「ターゲット プロパティ」に指定できません。
XAMLにデータバインディングを書く方法
データバインディングはマークアップ拡張機能を使って行い、XAMLファイルのUI要素に対し、Bindingキーワードに続く一連の宣言文字列で、「バインディング ソース」や「ソースプロパティ」を指定します。
「.NETオブジェクト」とWPFの「UI要素」を接続
次のようなC#のParsonクラスと、Label要素をデータバインディングで接続する簡単な例を見てみましょう。
1 2 3 |
public class Parson { public string Name { get; set; } } |
上記クラスのNameプロパティを、データバインディングする時は、XAMLには次のように書きます。
1 |
<Label Name="label" Text="{Binding Name}"/> |
バインディング ソースとなる、クラスのインスタンスは、DataContextプロパティに設定します。
1 |
this.DataContext = new Parson() { Name = "山田 太郎" }; |
実行結果
ほかのUI要素を参照する方法
同じ画面のUI要素間で、データバインディングをすることも可能です。 例えば、次のようなスライダー要素と、テキストボックスをBindingで接続し、スライダーとテキストボックスの値を双方向に同期することができます。
1 2 |
<TextBox Name="textbox" Width="50" Text="{Binding ElementName=slider, Path=Value}" /> <Slider Name="slider" Maximum="100" Minimum="0" SmallChange="1" IsSnapToTickEnabled="True"/> |
実行結果
上で紹介した2つの方法以外にも、WPFでは「XML」「ADO.NET」など、様々なオブジェクトをバインディングソースに設定できます。
C#とWPFのデータバインディング活用例
WPFアプリケーション開発で実際に使える活用例として、IValueConverterを使ったデータ変換を解説します。
IValueConverterでデータ変換
データベースを使用するWPFアプリでは、チェックボックスなどのBooleanの値を、データベース上では「YES/NO」や、「0/1」のような文字列で管理することがあります。
チェックボックスの値はtrue or falseのBoolaen型であるため、データベースの値をそのままチェックボックスにデータバインディングすると、正しく動作しません。
そのような時に、IValueConverterインターフェイスを実装した「コンバーター」を作成し、String型からBooladn型に変換することで、バインドの間にデータを変換を行うことができます。
コンバーターの作成
実際にC#で「コンバーター」を作ってみましょう。 今回は、文字列の“YES”と“NO”を、それぞれBoolean型のtrueとfalseに変換するコンバーターを作成します。
まず、次のようなIValueConverterインターフェイスを実装した新しいクラスを作成し、ConvertとConvertBackメソッドを実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[ValueConversion(typeof(bool), typeof(bool))] public class YesNoBooleanConverter: IValueConverter { //バインディング ソース→バインディングターゲットへの変換処理 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return "YES".eq(targetType); } //バインディングターゲット→バインディングソースの変換処理 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return true.eq(value) ? "YES" : "NO"; } } |
チェックボックスのIsCheckedに、上で作成したYesNoBooleanConverterを使用するようにXAMLを次のように編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<Window x:Class="SampleNaviApplication.Window1" 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:SampleNaviApplication" mc:Ignorable="d" Title="MainWindow" Height="200" Width="300"> <Window.Resources> <local:YesNoBooleanConverter x:Key="YesNoBooleanConverter"/> </Window.Resources> <Grid> <CheckBox IsChecked="{Binding StringFlag, Converter={StaticResource YesNoBooleanConverter}}"/> </Grid> </Window> |
ここまでの準備ができたら、バインディングソース(DataContext)に“YES/NO”のそれぞれの値を設定し、プログラム実行してみましょう。
バインディングソースにYESを設定した場合
1 |
this.DataContext = new SampleClass { StringFlag = "YES" }; |
実行結果
バインディングソースにNOを設定した場合
1 |
this.DataContext = new SampleClass { StringFlag = "NO" }; |
実行結果
- SE
- 実際にアプリを作ってみて、データバインディングへの理解が深まりました!
- PL
- データバインディングは、WPFの「MVVMモデル」開発において重要な概念のため、理解しておくと便利ですよ。
データバインディングはMVVMフレームワークでも重要な概念
WPFアプリ開発の現場では、MVVMパターン開発を支援する「Prism」などのフレームワークを利用することが多く、これらのフレームワークを利用するためには、データバインディングに関する知識が必要になります。WPFとデータバインディングを活用し、自身のスキルアップを図りましょう。