INotifyPropertyChangedではまった
のでその備忘録として
まあ言われてみればその通りなんだけどさ・・・
何に嵌まった
画面のプロパティをバインドするのに便利だぜと思っていたが、
その画面に遷移したとき、画面のプロパティを直接いじってはダメ
その画面に遷移したとき、画面のプロパティを直接いじってはダメ
ということ
それを知らないでやったら、INotifyPropertyChangedがそれ以降効かなくなった
間違ったコード
ビューモデルのソースを作成
まあタイマーを1秒ごとに起動してイベントあげるだけ
public class ViewModelsBase : INotifyPropertyChanged
{
System.Timers.Timer timer = new System.Timers.Timer();
private bool _isTimerPlus = false;
private int _timerCount = 0;
public ViewModelsBase()
{
timer.Interval = 1000;
timer.Elapsed += ViewModelsBase_OnTimer;
timer.Start();
}
public bool IsTimerPlus
{
get => _isTimerPlus;
set
{
_isTimerPlus = value;
OnPropertyChanged();
}
}
private void ViewModelsBase_OnTimer(object? sender, ElapsedEventArgs e)
{
IsTimerPlus = !IsTimerPlus;
}
/// <summary>
/// プロパティ変更通知
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// プロパティ変更通知
/// </summary>
/// <param name="propertyName"></param>
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
上のソースを継承して1秒ごとにその時刻を文字列として書き込む
class ViewModels2:ViewModelsBase
{
public ViewModels2()
{
PropertyChanged += ViewModels2_PropertyChanged;
}
private string _text = "Hello, World!";
public string TextHello
{
get => _text;
set
{ _text = value; OnPropertyChanged(); }
}
private void ViewModels2_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(IsTimerPlus))
{
TextHello = DateTime.Now.ToString();
}
}
}
書き換えたいラベルを適当な画面に追加
<Label
x:Name="CounterLabel"
Text="{Binding TextHello}"/>
BindContextに作ったviewModelクラスのインスタンスを設定だー
private ViewModels2 _viewModel = new ViewModels2();
public MainPage()
{
InitializeComponent();
BindingContext = _viewModel;
CounterLabel.Text = "ほげげ"; // ★直接書き換えてはいけない
}
はい。これで二度と_viewModelでイベントが発生しても画面が変化しなくなりました
正しくは、ConterLabel.Textを書き換えるのではなく
_viewModel.TextHello = "ほげげ";// ★ViewModelを介して書き換える
いや、全然書き換わらなくなっちゃって焦ったわ
おしまい
コメント
コメントを投稿