一、介绍
在WPF中使用MVVM方式进行数据绑定时需要继承并实现INotifyPropertyChanged接口,当属性的值发生修改时触发PropertyChanged事件的执行,PropertyChanged执行需要传递PropertyChangedEventArgs类型参数,而PropertyChangedEventArgs参数需要一个字符串类型的参数,这个参数就是调用属性的名称。
属性名字符串的获取方式在不断演变,文章列出几种属性名获取的实现方式,希望在开发中对大家有所帮助。
/// <summary>
/// Provides data for the <see langword='PropertyChanged'/> event.
/// </summary>
public class PropertyChangedEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref='System.ComponentModel.PropertyChangedEventArgs'/>
/// class.
/// </summary>
public PropertyChangedEventArgs(string? propertyName)
{
PropertyName = propertyName;
}
/// <summary>
/// Indicates the name of the property that changed.
/// </summary>
public virtual string? PropertyName { get; }
}
二、第一种
public class MainViewModel : System.ComponentModel.INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion INotifyPropertyChanged
}
这种实现方式是开始学习WPF MVVM时最多使用的,简单直接,属性名字符串用硬编码方式写进代码中,应用方式如下:
public class MainViewModel : System.ComponentModel.INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion INotifyPropertyChanged
bool _isChecked1;
public bool IsChecked1
{
get { return _isChecked1; }
set { _isChecked1 = value; OnPropertyChanged("IsChecked1"); }
}
}
开发者需要在属性的Set方法中将属性名字符串传递到OnPropertyChanged方法,字符串的值必须要和属性名完全一致,多一个空格也会导致失败。这种写法的缺点是容易写错属性名字符串,并且需要修改属性名时还需要开发者手动修改对应的属性名字符串,因此这种实现方式一般不推荐在开发中使用。
三、第二种
public class MainViewModel : System.ComponentModel.INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void OnPropertyChanged(Expression<Func<MainViewModel, object>> propertyExpression)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(NameForProperty(propertyExpression)));
}
private string NameForProperty<TDelegate>(Expression<TDelegate> propertyExpression)
{
Expression body;
var expression = propertyExpression.Body as UnaryExpression;
if (expression != null)
body = expression.Operand;
else
body = propertyExpression.Body;
var member = body as MemberExpression;
if (member == null)
throw new ArgumentException("Property must be a MemberExpression");
return member.Member.Name;
}
#endregion INotifyPrope