最小化绑定属性上的WPF样板代码
本文关键字:代码 WPF 绑定 属性 最小化 | 更新日期: 2023-09-27 18:18:07
考虑一个具有许多输入字段的WPF对话框,这些字段绑定到视图模型中的属性。例如
...
<TextBox Text="{Binding FirstName}">
...
public string FirstName {
get { return mFirstName; }
set {
if (mFirstName == value) return;
mFirstName = value;
OnPropertyChanged("FirstName");
}
}
由于有数十个这样的字段,我想尽量减少要编写的样板c#代码。我有什么选择?
如果您可以选择使用基类,请考虑从以下内容继承视图模型对象:
public abstract class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value))
{
return false;
}
storage = value;
// ReSharper disable once ExplicitCallerInfoArgument
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected void OnPropertiesChanged(params string[] propertyNames)
{
foreach (string propertyName in propertyNames)
{
// ReSharper disable once ExplicitCallerInfoArgument
OnPropertyChanged(propertyName);
}
}
}
示例用法,显示样板文件大大减少了:
public sealed class ViewModel : BindableBase
{
private string name;
public string Name
{
get { return name; }
private set { SetProperty(ref name, value); }
}
}
(如果你不能使用基类(例如,你已经有一个或正在使用框架元素的属性),你仍然可以选择直接在相关类中添加类似的支持)
我可以让你的代码更容易转换成代码段。
if (mFirstName != value) {
mFirstName = value;
OnPropertyChanged("FirstName");
}
如果仅仅是编写代码所花费的时间就很痛苦,并且您经常使用WPF,那么代码片段也可能有用。我知道在Sublime Text, VS Code和Visual Studio中,snippet是无价的。除此之外,我认为它就是你能看到的最基本的内容了,除非有什么我没看到的
我使用Fody在编译时注入属性更改的代码。你的类获得一个[ImplementPropertyChanged]属性,然后你的{get;设置;}属性成为编译后代码中的通知属性。
https://github.com/Fody/PropertyChanged首先,我猜你已经在用微软了。Prism,您可以在后台删除字符串并从CallerMemberNameAttribute中获利,因此您的代码看起来像这样:
public string FirstName {
get { return mFirstName; }
set {
if (mFirstName == value) return;
mFirstName = value;
OnPropertyChanged();
}
}
这也等价于c# 6.0的nameof(FirstName)
运算符。
第二,您可以深入研究AOP并将样板抽象为一个属性。处理这个问题的AOP框架之一是PostSharp,使用它你的代码可以像这样:
[NotifyPropertyChanged]
public class Customer
{
public string FirstName { get; set; }
虽然它不是免费的,而且AOP有它的缺点(感谢Evk)。
类似的问题已经被问到1,2,遗憾的是,目前似乎没有最佳答案,因为这是每个人的痛苦。