かきスタンプ

福岡でフリーランスの物流系のエンジニアやってます。

C#(MVVM):Vとバインドしたプロパティに対して VM側で値を変更する処理を記述する場合、アクセサでなくプライベート変数に変更をかけた方がいいのではないかという話。

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回で済む。
もしくは編集用の一時変数を用意して、最後にアクセサをコールするという方法でもいいかも。