为什么后台绑定的值改变了前台不发生变化了?
针对这个初学者很容易弄错的问题,这里介绍一下INotifyPropertyChanged的用法
INotifyPropertyChanged:用于绑定属性更新
1 /// <summary> 2 /// 实体基类,实现了属性通知 3 /// </summary> 4 public class BaseEntity : INotifyPropertyChanged 5 { 6 public event PropertyChangedEventHandler PropertyChanged; 7 8 /// <summary> 9 /// 触发属性通知 10 /// 这里用了一个特性的小技巧,就是CallMemberName 11 /// 通过反射来获取调用者的名称,从而避免每一次调用方法都需要将属性名称传入方法 12 /// </summary> 13 /// <param name="propertyName"></param> 14 [NotifyPropertyChangedInvocator] 15 protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 16 { 17 var handler = PropertyChanged; 18 if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 19 } 20 }
学生类继承自实体基类,通过继承的OnPropertyChanged方法来通知属性已经发生改变
1 /// <summary> 2 /// 学生类 3 /// </summary> 4 public class Student : BaseEntity 5 { 6 private string _name; 7 8 /// <summary> 9 /// 名字 10 /// </summary> 11 public string Name 12 { 13 get { return _name; } 14 set 15 { 16 _name = value; 17 OnPropertyChanged(); 18 } 19 } 20 21 private int _age; 22 23 /// <summary> 24 /// 年龄 25 /// </summary> 26 public int Age 27 { 28 get { return _age; } 29 set 30 { 31 _age = value; 32 OnPropertyChanged(); 33 } 34 } 35 36 private double _score; 37 38 /// <summary> 39 /// 分数 40 /// </summary> 41 public double Score 42 { 43 get { return _score; } 44 set 45 { 46 _score = value; 47 OnPropertyChanged(); 48 } 49 } 50 }
在ViewModel中声明一个Student,并且生成相应事件
public class MainWindowViewModel { public Student LiLei { get; set; } public MainWindowViewModel() { InitStudentInfo(); StartUpdateScore(); } //初始化学生信息 private void InitStudentInfo() { LiLei = new Student { Name = "李雷", Age = 14, Score = 91.5 }; } //开始更新分数 private void StartUpdateScore() { //定义一个定时器,改变分数值,若小于100分,那么增加,否则将到达一个特定分数 var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) }; timer.Tick += (sender, e) => { if (LiLei.Score < 99) { LiLei.Score++; } else { LiLei.Score = 89.5; } }; timer.Start(); } }
前台Xaml
1 <Grid> 2 <StackPanel> 3 <TextBlock> 4 <Run Text="姓名:"/> 5 <Run Text="{Binding LiLei.Name}"/> 6 </TextBlock> 7 <TextBlock> 8 <Run Text="年龄:"/> 9 <Run Text="{Binding LiLei.Age}"/> 10 </TextBlock> 11 <TextBlock> 12 <Run Text="分数:"/> 13 <Run Text="{Binding LiLei.Score}"/> 14 </TextBlock> 15 </StackPanel> 16 </Grid>
后台绑定
1 public MainWindow() 2 { 3 InitializeComponent(); 4 this.DataContext = new MainWindowViewModel(); 5 }
效果图:
一个简单是示意例子,其实在大部分的Mvvm框架中,都有一些类是实现了属性通知的,会有相应的方法可以调用,一般不用自己去实现INotifyPropertyChanged接口