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
是管理属性变更的最佳实践!