SetProperty
是 MVVM(Model-View-ViewModel) 模式中用于实现 属性变更通知(INotifyPropertyChanged) 的核心方法,主要用于在属性值变化时自动更新 UI 绑定。
1. SetProperty
的基本作用
更新字段值:修改属性的私有字段(backing field)。
触发通知:如果值发生变化,自动发出
PropertyChanged
事件,通知 UI 更新。避免重复更新:如果新值和旧值相同,则不触发事件,提高性能。
2. SetProperty
的典型实现
通常在 ViewModel 基类 中定义,例如:
(1)基础版本(带 [CallerMemberName]
自动获取属性名)
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false; // 值未变化,不触发更新
field = value; // 更新字段值
OnPropertyChanged(propertyName); // 触发通知
return true;
}
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
参数说明
ref T field
:属性的私有字段(如axisXStatusInfo
)。T value
:要设置的新值。[CallerMemberName] string propertyName
:自动获取调用该方法的属性名(如"AxisXStatusInfo"
)。
返回值
true
:值已更改,并触发了PropertyChanged
事件。false
:值未更改,不触发事件。
(2)扩展版本(支持自定义回调)
protected bool SetProperty<T>(
ref T field,
T value,
Action<T>? onChanged = null,
[CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
onChanged?.Invoke(value); // 可选:值变化后执行额外逻辑
OnPropertyChanged(propertyName);
return true;
}
用法示例
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value, (newValue) =>
{
Console.WriteLine($"Name 从 {_name} 变为 {newValue}");
});
}
3. 如何在 ViewModel 中使用 SetProperty
?
假设有一个 ViewModel
继承自 ObservableObject
:
public class MainViewModel : ObservableObject
{
private string _status;
public string Status
{
get => _status;
set => SetProperty(ref _status, value); // 自动触发 UI 更新
}
private int _count;
public int Count
{
get => _count;
set => SetProperty(ref _count, value, onChanged: (newCount) =>
{
Console.WriteLine($"Count 更新为 {newCount}");
});
}
}
4. 为什么需要 SetProperty
?
简化
INotifyPropertyChanged
的实现:避免在每个属性的set
里手动写OnPropertyChanged
。提高性能:仅在值真正变化时触发事件。
支持自动属性名推断:
[CallerMemberName]
避免硬编码属性名,减少错误。
5. 常见问题
(1)SetProperty
和 OnPropertyChanged
的区别?
SetProperty
:用于 修改属性值并触发通知。OnPropertyChanged
:仅 手动触发通知(适用于计算属性或依赖属性)。
(2)如果不使用 SetProperty
,传统写法是怎样的?
private string _name;
public string Name
{
get => _name;
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
}
SetProperty
让这段代码更简洁、更安全。
总结
功能 | SetProperty 的作用 |
---|---|
更新字段值 | field = value |
自动触发 UI 更新 | 调用 OnPropertyChanged |
避免重复更新 | 检查新旧值是否相同 |
支持回调 | 可选 onChanged 逻辑 |
自动获取属性名 | [CallerMemberName] |
如果你的项目使用 WPF / MAUI / Xamarin / Avalonia 等 MVVM 框架,SetProperty
是管理属性变更的最佳实践!