Vとバインドしたプロパティに対して VM側で値を変更する処理を記述する場合、アクセサでなくプライベート変数に変更をかけた方がいいのではないかという話。
以下、サンプルソースです。
今回の話題に必要なパートのみを抜粋した状態です。
<TextBox Text="{Binding Path=MyVmString01, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" /> <Button Content="AddText" Command="{Binding Path=AddTextCommand}" />
/// <summary> /// プロパティ /// </summary> private string _myVmString01 = "初期値"; public string MyVmString01 { get { return this._myVmString01; } set { if (this._myVmString01 == value) { return; } this._myVmString01 = value; base.OnPropertyChanged(nameof(this.MyVmString01)); } } /// <summary> /// リレーコマンド /// </summary> private RelayCommand _addTextCommand; public RelayCommand AddTextCommand { get { return this._addTextCommand = this._addTextCommand ?? new RelayCommand(this.AddSpecialCharacter); } } /// <summary> /// メソッド /// </summary> private void AddSpecialCharacter() { _myVmString01 += "x"; OnPropertyChanged(nameof(this.MyVmString01)); }
public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } }
概要
- MyVmString01 は、V側の TextBox とバインドしている。
- MyVmString01 の変更は、アクセサを通して V側に通知される。(OnPropertyChangedメソッド。)
- AddTextCommand は、V側の Button とバインドしている。
- AddTextCommand から AddSpecialCharacter() がコールされ、_myVmString01 の内容が変更される。
話がしたいのは、AddSpecialCharacter() メソッド。
『myVmString01 += "x" 』と、プライベート変数の myVmString01 に変更を加えているけど、「別に『MyVmString01 += "x";』と書いても結果は一緒だから、どっちでもいいんじゃね?」と思ってた。
が、setterを使うと 変更をV側に伝えるために OnPropertyChangedが実行される事になり、V側に渡す内容を取得するために getも実行される。 (getアクセサにブレークポイントを置くと分かりやすい。)
つまり、メソッドに 1000回書き換えるループ処理があれば、1000回 V側に通知され、1000回 getが実行される。
非常にメモリに優しくないので、プライベート変数を編集した後、OnPropertyChanged をコールすると、getが1回で済む。
もしくは編集用の一時変数を用意して、最後にアクセサをコールするという方法でもいいかも。