WPFとVB.NETでDataContextやBinding、INotifyPropertyChangedの練習
DataContextやBindingのテスト
キーワードは
DataBinding:縛る、束ねる 紐付けるかな
DataContext:文脈、脈絡 これも繋がりみたいな感じね
INotifyPropertyChanged:通知 Notifyが通知でこれはそのまま
Implements:用具、実装 ググってると実装はたまによく聞く
オレンジと緑の四角はBorderコントロール
このBorderの縦横の大きさや色をスライダーやボタンを使って変化させている
クリックした方のBorderだけ変化する
こっちを変えたらあっちも変わる、あっちを変えたらこっちも変わるとかの
コントロール同士の連携みたいなのをBindingを使うと自動で処理してくれる
デザイン画面とXAML
VBコード
簡単なBindingの例だと上のアプリではスライダーとその値を表示しているTextBlockがBindingで連携している
このBindingはXAMLのほうで指定している
TextblockのTextプロパティにsld1と名前をつけたSliderの値ValueをBinding
ElementNameに連携するコントロールを指定、ここではsld1
Pathに連携するプロパティを指定、ここではValue
StringFormatは表示形式の指定で0.0だと小数点一桁まで表示になる
これだけでスライダーを動かすと自動でその値をTextBlockに表示されるようになる
TextBlockのTextとSliderのValueが同期する感じ
SliderのValueに{Binding Width}ってBinding指定をしているのはTextBlockとは関係なくてDataContextのWidthプロパティとのBindingになる
今回の場合だと
いろいろなプロパティを入れておくクラスを用意
ExDataって名前をつけたクラスを作ったのがこの部分で、今回はまだだけど最終的にはシリアライズしてファイルに保存する予定
Width、HeightがDouble型、BackgroundColorはSolidColorBrush型?
基本的には3つのプロパティをもたせただけの簡単なクラスなんだけど
例えばこのクラスのWidthとスライダーのValueをBindingさせた状態で、どちらか片方の値が変化した時にもう一方の値も変化させるっていう双方向のBindingにしたい場合は、このクラスのWidthを変化させた時に相手側に通知する必要がある
そのためには通知する機能を持たせる必要がある、それが
INotifyPropertyChangedっていうインターフェイスってものらしい
これは
プロパティ - Programming/.NET Framework - 総武ソフトウェア推進所ここを参照した、丁寧に説明されているのでここ見たほうが早い
http://smdn.jp/programming/netfx/property/#INotifyPropertyChanged
って打ってエンターキー押すと
ってのが自動で入力される
どうやら必要なEventらしい、これが実行されると変更が通知されるってことなのかな
続いて、このEventを実行させるメソッド?が必要みたいで
Private Sub OnPropertyChanged(name As String)
RaiseEvent
End Sub
RaiseEventってのがEventを実行させる宣言みたいなものかな、ここまで入力するとEventの一覧表が出てくる、一覧表と言ってもさっき自動で追加されたPropertyChanged一個しかないけどね、面白い
PropertyChangedイベントを選んで入力すると引数が要るみたいで
senderはこのクラス自身のMeで、もう一つはPropertyChangedEventArgs
これで通知機能を持たせることができたになるのかな
あとは通知するタイミング
変更(Set)した直後に通知したいから
例えばWidthってプロパティの場合は
プロパティのSetのところにさっきのEventを実行させるメソッドのOnPropertyChangedを書く、引数に持たせるのはプロパティの名前
残り二つのプロパティにもSetのところにOnPropertyChangedを書く
以上でプロパティの変更通知機能付きのExDataクラスの完成
Borderを全部を入れるリスト
ExDataを全部入れるリスト
選択中のBorderを入れる
アプリ起動時の初期設定
縦横の大きさや色の指定はしない
SetBindingを使ってBindingする各プロパティを指定
Tagには連番を入れているけど、必要じゃなかった
左クリックで選択中のBorderを切り替えるのでそのイベントに関連付け
作成したBorderをリストに入れる
最後の call DataResetは
2つのExDataクラスを作成して各プロパティに値を指定してリストに追加しているのが、27行目まで
14行目から19行目までが1つ分のExDataクラスを作成して各プロパティに値を指定している
この6行分は
DataList.Add(New ExData With {.Height = 50, .Width = 50, .BackgroundColor = New SolidColorBrush(Colors.Orange)})
っていう1行でもできるみたいで、これは慣れたらこっちのほうがいいのかな?
29行目からの3行で各BorderのDataContextに各ExDataを指定している
これでBorderとExDataが連携できるBindingが完了
35行目はgrid1(Grid)のDataContextに今選択中のBorderのDataContext(中身はExData)を指定している、これでgrid1の中に配置されているコントロールはこのDataContextを参照できるみたいなので、わざわざ1つ1つのコントロールのDataContextに指定しなくても良くなっている
赤色のところがgrid1の中になる、ほぼ全部
実際にこのDataContextとBindingしているのは
19行目と24行目のSliderでそれぞれ自身のValueをDataContextのなかのWidthとHeightにBindingしている
Bindingの関係はこうなって、どれかの値が変更されたら他のも全部変更されて同じ値になるっていう動作、になるはずだったんだけど失敗していてBorderのWidthを変更してもExDataのWidthが変化しない、これを直したのは2日後の記事
Borderをクリックした時
選択中のBorder用の変数ImaBorderにクリックされたBorderを入れるgrid1のDataContextを選択中のBorderのDataContextにする
これでクリックされたBorderの横幅、高さの値がSliderに反映されるしSliderを動かすとBorderのサイズが変更されるようになる
各ボタンをおした時の動作
Button1は選択中のBorderのDataContextのExDataを読み取ってその中の色と横幅を変更している
Button2はExDataのリスト中のExDataの中の色と横幅を変更している
Button3は選択中のBorderの色と横幅を変更している、けど今回では失敗しているのでコメントアウトしている、これを実行するとBorderは変化するけどSliderとExDataとのBindingが外れてしまったような状態になって、Sliderを動かしてもサイズ変更しなくなる
WindowsFormアプリ作成でのコントロール同士の連携はめんどくさかった
Aを変えたらBも変える、Bを変えたらAも変えるって普通に書くと無限ループのはずなんだけど空気を読んでくれているのかループしないようになっていた気がする
WPFでは同じように書くと無限ループするのでフラグを用意して処理していた
この前まで作っていたカラーピッカーがそれ
でも慣れていないせいかBindingもめんどくさい感じがするし難しいw
参照したところ
INotifyPropertyChanged インターフェイス (System.ComponentModel)
https://msdn.microsoft.com/ja-jp/library/system.componentmodel.inotifypropertychanged(v=vs.110).asp
https://msdn.microsoft.com/ja-jp/library/system.componentmodel.inotifypropertychanged(v=vs.110).asp
コード全部
Wpf_test96_データバインドDataContext - Visual Studio Team Services
https://gogowaten.visualstudio.com/DefaultCollection/WPF/_git/WPF_test6?path=%2FWpf_test96_%E3%83%87%E3%83%BC%E3%82%BF%E3%83%90%E3%82%A4%E3%83%B3%E3%83%89DataContext&version=GBmaster&_a=contents
https://gogowaten.visualstudio.com/DefaultCollection/WPF/_git/WPF_test6?path=%2FWpf_test96_%E3%83%87%E3%83%BC%E3%82%BF%E3%83%90%E3%82%A4%E3%83%B3%E3%83%89DataContext&version=GBmaster&_a=contents
続きは2日後の