データバインディングのおべんきょ。その4。
前回のあらすじ
あ、あ、あれ? 'とりこびと' いないぢゃん!(ToT)
なんとも切ないお話です。もちろん涙が止まりません。バインドしたリストにプログラムコードから新しく追加しても ComboBox1 に反映されませんでした。
なんとかこの問題もズバッと解決したいところですね。いろいろ調べた結果、いくつか方法があるようですので順番に書いていきますね。
まず、一つ目です。さくっと書きます。
List クラス使うのやめちゃう!
ええ、とてもつらいです。つらいですが、仕方ありません。List クラス単独では難しそうなんですもの。なぜかって?
IBindingList インターフェイスを実装してないからです。
MSDN だとこちら↓。
MSDN:IBindingList インターフェイス(http://msdn2.microsoft.com/ja-jp/library/system.componentmodel.ibindinglist(VS.80).aspx)
どうやら、IBindingList インターフェイス の メンバ ListChanged イベントがリストの変更通知としての機能を果たすようですね。で、なんかそれっぽいクラスはないかな~って探してみると・・・
MSDN:BindingList クラス(http://msdn2.microsoft.com/ja-jp/library/ms132679(VS.80).aspx)
いいもん持ってんじゃねーか♪
ええまったく、.NET Framework のクラスライブラリっていろんなクラスがありますね。
前回使用した Form1 のコードを以下のように修正します。
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Public Class Form1
Private _entertainerList As BindingList(Of WankumaEntertainer)
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Me._entertainerList = New BindingList(Of WankumaEntertainer)
Me._entertainerList.RaiseListChangedEvents = True
Me._entertainerList.Add(New WankumaEntertainer("ぽぴ王子"))
Me._entertainerList.Add(New WankumaEntertainer("アクア"))
Me._entertainerList.Add(New WankumaEntertainer("R・田中一郎"))
Me.ComboBox1.DataSource = Me._entertainerList
Me.ComboBox1.DisplayMember = "Name"
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me._entertainerList.Add(New WankumaEntertainer("とりこびと"))
End Sub
End Class
前回 List クラスしていた部分を BindingList に変更しただけですね。RaiseListChangedEvents プロパティは ListChanged イベントを発生させるかどうかを設定できるようです。なので今回は 発生させたいので True にしてあります。(あ、System.ComponentModel を Imports してます。BindingList クラスはSystem.ComponentModel 名前空間にありますので。)
作業はこれでおしまいです。早速実行してみてください。前回、Button1 をクリックすると _entertainerList に新しく 'とりこびと' という Name プロパティ に設定された WankumaEntertainer を追加するコードになっていました。その Button1 をクリックして ComboBox1 のリストが変更されるか確認してみましょう。
新しい自分(とりこびと)がいる!!
というわけで、BindingList クラスというとっても便利なクラスを使用する方法でリストの変更をコントロールに通知する方法でした。
・・・って、今回はそう簡単には終わらせないぞ!フヒヒ
というのも、リストの変更は通知されるようになりましたが、リストの要素の変更はどうでしょう?今回だと _entertainerList に含まれる WankumaEntertainer クラスのインスタンスの Name プロパティが変更された場合、ちゃんと変更されるでしょうか?
ちょっと試してみましょう。デザイナから Form1 にButton を一つ追加して(Button2 で。)Form1 を以下のように変更します。
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Public Class Form1
Private _entertainerList As BindingList(Of WankumaEntertainer)
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Me._entertainerList = New BindingList(Of WankumaEntertainer)
Me._entertainerList.RaiseListChangedEvents = True
Me._entertainerList.Add(New WankumaEntertainer("ぽぴ王子"))
Me._entertainerList.Add(New WankumaEntertainer("アクア"))
Me._entertainerList.Add(New WankumaEntertainer("R・田中一郎"))
Me.ComboBox1.DataSource = Me._entertainerList
Me.ComboBox1.DisplayMember = "Name"
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me._entertainerList.Add(New WankumaEntertainer("とりこびと"))
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
For Each entertainer As WankumaEntertainer In Me._entertainerList
If entertainer.Name = "とりこびと" Then
entertainer.Name = "とりこびと(仮)"
End If
Next
End Sub
End Class
Button2 をクリックすると _entertainerList に 'とりこびと' という Name プロパティ に設定された WankumaEntertainer クラスのインスタンスがあれば、そのName プロパティを'とりこびと(仮)'に変更するコードです。
ではでは、実行してみましょう。Button1 をクリックして 'とりこびと' を追加し、Button2 をクリックして変更してみてください。でもってその後 ComboBox1 のリストを確認してみてください。
うひぃ~!変化なし!!(ToT)
そうです。プログラムコードから_entertainerList の要素の変更に対して行った変更が反映されません。・・・またまた困りましたね。
・・・と、困ったところで今回も次回につ・づ・く♪