Windows Formsで配列の要素に対してバインドする方法
はじめに
Windows Formsで配列の要素に対してバインドしたい時が結構あります。
同じコントロールを複数配置した場合も、配列で管理した方が楽な時があります。
前提
- Window.Forms
- VB 2017
- .NET Framework 4.6.1
ソースコード
ささっと以下のコード。
Imports System.ComponentModel
Public Class Form1
Private VM As New ViewModel
Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TextBox1.DataBindings.Add(New Binding("Text", VM.Inputs(0), "Value"))
TextBox2.DataBindings.Add(New Binding("Text", VM.Inputs(1), "Value"))
TextBox3.DataBindings.Add(New Binding("Text", VM.Inputs(2), "Value"))
End Sub
Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
VM.Update()
End Sub
Private Class ViewModel
Public Inputs As t()
Sub New()
Inputs = {
New t With {.Value = "a"},
New t With {.Value = "b"},
New t With {.Value = "c"}
}
End Sub
Sub Update()
Inputs(0).Value = "1"
Inputs(1).Value = "2"
Inputs(2).Value = "3"
End Sub
Class t
Implements INotifyPropertyChanged
Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private _Value As String
Property Value As String
Get
Return _Value
End Get
Set
_Value = Value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(NameOf(Value)))
End Set
End Property
End Class
End Class
End Class
試す
ばっちり
なにがおきたか
配列の用意
ViewModelクラス内では、Inputs
の要素に対してクラスを指定します。そして、Inputs
の要素に対してバインドする為、Inputs
自身はただのメンバでよいです。
Private Class ViewModel
Public Inputs As t()
' ~~中略~~
End Class
配列の「要素」となるプロパティの用意
代わりに、Inputs
の要素に対して指定したクラスとそのプロパティに対しては、プロパティを用意し、INotifyPropertyChanged
によるPropertyChanged
イベントを発火(Raise)させるようにします。
はい、要素自身をINotifyPropertyChanged
を継承したクラスにすることで、個々の要素に対してバインド可能なプロパティを設定することに成功しています。
Private Class ViewModel
Public Inputs As t()
' ~~中略~~
Class t
Implements INotifyPropertyChanged
Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private _Value As String
Property Value As String
Get
Return _Value
End Get
Set
_Value = Value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(NameOf(Value)))
End Set
End Property
End Class
End Class
配列とその要素の初期化
バインド先がnullだと普通にヌルポされちゃいます。ちゃんと配列とその要素を初期化しましょう。ついでに
' ~~前略~~
Private Class ViewModel
Public Inputs As t()
Sub New()
Inputs = {
New t With {.Value = "a"},
New t With {.Value = "b"},
New t With {.Value = "c"}
}
End Sub
Sub Update()
Inputs(0).Value = "1"
Inputs(1).Value = "2"
Inputs(2).Value = "3"
End Sub
' ~~中略~~
End Class
バインドの設定
フォームロード時に、各テキストボックスに対して、ViewModelクラスのメンバにある配列Inputs
の要素と結び付けます。もちろん個々の要素に対してバインドするので、配列へのインデックスはきちんと決めてあげましょう。
' ~~前略~~
Public Class Form1
Private VM As New ViewModel
Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TextBox1.DataBindings.Add(New Binding("Text", VM.Inputs(0), "Value"))
TextBox2.DataBindings.Add(New Binding("Text", VM.Inputs(1), "Value"))
TextBox3.DataBindings.Add(New Binding("Text", VM.Inputs(2), "Value"))
End Sub
' ~~中略~~
End Class
この時、指定されたインデックスに当てはまる要素がない場合、エラーが起きます。
あと、変な設定すると正しくバインドされませんでした(3敗)
' ~~前略~~
Public Class Form1
Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' エラーになる:存在しない(ようにした)インデックスを指定
TextBox1.DataBindings.Add(New Binding("Text", VM.Inputs(5000), "Value"))
' エラーになる:プロパティ「名」としてのInputs(2)は存在しない。特に「(2)」が存在しない
TextBox3.DataBindings.Add(New Binding("Text", VM, "Inputs(2).Value"))
' エラーにはならないし、初回だけ値は設定されるけど、実はバインドされてない
TextBox2.DataBindings.Add(New Binding("Text", VM.Inputs(1).Value, ""))
End Sub
' ~~中略~~
End Class
Author And Source
この問題について(Windows Formsで配列の要素に対してバインドする方法), 我々は、より多くの情報をここで見つけました https://qiita.com/ueruku/items/b7ee16dbce4e994e9de5著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .