Edited at

Windows Forms のデータバインディング

More than 3 years have passed since last update.


Windows Forms のデータバインディング

WPF では当然のように使用されるデータバインディングですが、Forms でもデータをバインドできます。

そこで、簡単なプログラムを作成してみます。

作成するプログラムは、名前を入力しボタンをクリックしたら、入力された名前をメッセージボックスに出力するだけのプログラムです。


モデルの作成

バインドするモデルを作成します。

今回は、Name プロパティを持つクラスを Form クラスの内部に作成してみます。入れ子にする意味はありません。

Name プロパティの値が変わったときに画面の表示も更新したいので、INotifyPropertyChanged も実装します。

Form1.vb


Imports System.ComponentModel

Public Class Form1

Public Class Model
Implements INotifyPropertyChanged

Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

Private _name As String
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(NameOf(Name)))
End Set
End Property
End Class

End Class


バインドの設定

フォームデザイナでバインドを設定する場合は、モデルクラスがコンパイル済みでないと参照できないので、一度ソリューションをコンパイルします。

フォームデザイナでバインド先のテキストボックスを選択し、プロパティの(DataBindings) Text のドロップダウンを開き、Add Project Data Source を選択します。

Data Source Type に Object を選択し、Form1.Model を選択して完了させます。

今回は Model クラスにプロパティが一つなので、自動的に Name プロパティにバインドされますが、プロパティが複数存在する場合は、バインドするプロパティを選択します。




モデルインスタンスの設定

この状態で実行しても、モデルがインスタンス化されませんので、プログラムでインスタンス化とDataSourceへの設定を行います。

モデルは、バインド以外でも使用しますので、メンバ変数に保存するようにします。

取りあえず、Form1 のコンストラクタにデザイナで作成されたModelBindingSource.DataSource にモデルインスタンスを代入します。

Click ボタンのイベントハンドラにモデルインスタンスの Name を MessageBox で表示するようにすると、テキストボックスで入力された値がモデルインスタンスの Name プロパティに自動で設定されますので入力した値がメッセージボックスで表示されます。

Clear ボタンのイベントハンドラでモデルインスタンスの Name プロパティに空文字列を設定すると、PropertyChangedイベントが発生し、テキストボックスの表示も自動で更新されます。

最終的な Form1.vb


Imports System.ComponentModel

Public Class Form1

Private _model As New Model()

Public Sub New()

InitializeComponent()

ModelBindingSource.DataSource = _model

End Sub

Public Class Model
Implements INotifyPropertyChanged

Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

Private _name As String
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(NameOf(Name)))
End Set
End Property
End Class

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
MessageBox.Show(_model.Name)
End Sub

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
_model.Name = String.Empty
End Sub

End Class


コードによるバインディング

フォームデザイナでバインドすると、モデルのプロパティ名を変更したときにリファクタリングされません。

NameOf演算子を使えば文字列リテラルを無くせますので、リファクタリング対象になります。


TextBox1.DataBindings.Add(New Binding(NameOf(TextBox1.Text), _model, NameOf(_model.Name))

ちょっと長めになりますが、スニペットにすれば大丈夫でしょう。