Xamarin中如何避免在每个属性的setter中调用NotifyPropertyChanged?
解决Xamarin中重复编写INotifyPropertyChanged属性的方案
绝对有办法摆脱这种重复代码的折磨!我给你列几个最常用的方案,从简单到进阶都有:
1. 封装通用的SetProperty方法到基类
这是最基础且不需要额外依赖的方案。你可以先创建一个ViewModel基类,把属性变更的逻辑封装成一个通用方法:
public class BaseViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected bool SetProperty<T>(ref T backingField, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer<T>.Default.Equals(backingField, value)) return false; backingField = value; OnPropertyChanged(propertyName); return true; } protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
之后你的属性就可以简化成这样,再也不用写重复的判断和通知代码:
private string _name; public string Name { get => _name; set => SetProperty(ref _name, value); }
这里用到了[CallerMemberName]特性,能自动获取属性名,不用手动传参,减少出错概率。
2. 使用MVVM框架的特性生成(推荐!)
现在最流行的是用CommunityToolkit.Mvvm这个官方维护的库(完全免费,无额外依赖),它利用.NET的源代码生成器,只需要给私有字段加个特性,就能自动帮你生成完整的属性和通知逻辑。
步骤很简单:
- 安装NuGet包:
CommunityToolkit.Mvvm - 让你的ViewModel继承自
ObservableObject - 给私有字段加上
[ObservableProperty]特性:
using CommunityToolkit.Mvvm.ComponentModel; public class MyViewModel : ObservableObject { [ObservableProperty] private string _name; [ObservableProperty] private int _age; }
编译之后,源代码生成器会自动生成对应的Name和Age属性,包含完整的变更判断和NotifyPropertyChanged调用,甚至还会生成OnNameChanged这样的可选重写方法,方便你在属性变更后做额外逻辑。
除了这个,像Prism、MvvmCross这类成熟的MVVM框架也有类似的简化方案,但CommunityToolkit.Mvvm是最轻量且官方支持的,推荐优先用它。
3. 用T4模板自动生成代码
如果你不想引入第三方库,也可以用Visual Studio自带的T4文本模板来批量生成属性代码。比如你可以写一个模板,定义好字段列表,然后自动生成对应的属性代码块。
举个简单的T4模板示例:
<#@ template language="C#" #> <#@ output extension=".cs" #> public class MyViewModel : BaseViewModel { <# var properties = new[] { new { Type = "string", Name = "FirstName" }, new { Type = "string", Name = "LastName" }, new { Type = "int", Name = "Age" } }; foreach (var prop in properties) { #> private <#= prop.Type #> _<#= prop.Name.ToLower() #>; public <#= prop.Type #> <#= prop.Name #> { get => _<#= prop.Name.ToLower() #>; set => SetProperty(ref _<#= prop.Name.ToLower() #>, value); } <# } #> }
每次修改字段列表后,右键模板选择“运行自定义工具”,就能自动生成对应的属性代码,适合需要批量创建属性的场景。
内容的提问来源于stack exchange,提问作者Moha the almighty camel
相关产品推荐
相关产品推荐

