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
?是管理屬性變更的最佳實踐!