我开发了很多视图模型:
1)所有必须实现INotifyPropertyChanged才能绑定到UI。
2)属性设置者必须在更改时提升PropertyChanged。
3)PropertyChanged事件必须提供适当的属性名称。
如果你(像我一样)写下这样的东西:
public string Name
{
get
{
return _name;
}
set
{
if (_name != value)
{
_name = value;
RaisePropertyChanged("Name");
}
}
}
然后像这样重构这个方法,有时忘记更新属性名称文字:
string _fundName;
public string FundName
{
get
{
return _fundName;
}
set
{
if (_fundName != value)
{
_fundName = value;
RaisePropertyChanged("Name");
}
}
}
然后花一天时间来调试为什么你的UI没有刷新,数据绑定无法正常工作。
然后我们所需要的只是某种魔力。
如果我只需要写这个怎么办:
[Magic] // implicit transformation
public string FundName { get; set; }
或者如果我有很多属性:
[Magic]
public class MyViewModel
{
public string FundName { get; set; }
public string FundType { get; set; }
[NoMagic] // suppress transformation
public int InternalId { get; set; }
}
所以我刚刚开发了一个MSBuild任务来在构建(http://kindofmagic.codeplex.com)之后完成这个魔术。
问题是,你想要更多什么样的神奇后处理?
INotifyPropertyChanging的自动实现是否有意义?
答案 0 :(得分:4)
试试这个
http://code.google.com/p/notifypropertyweaver/
这是关于它的博客文章
http://codesimonsays.blogspot.com/2010/11/attempting-to-solve-inotifypropertychan.html
它支持您请求的属性
虽然这些是可选项并且专为微调而设计。大多数注射是通过分析现有的IL来按惯例完成的。
答案 1 :(得分:1)
无论如何我会尝试你的代码,它有可能相当节省时间。这绝对应该是.NET的一部分。
答案 2 :(得分:1)
如果我们要生成花哨的代码,我想我更喜欢一种更容易生成DependancyProperties的方法。我使用的snippit肯定是有帮助的,但是当你有改变和强制回调以及元数据选项时,我不是一个粉丝,代码看起来是多么混乱。也许我会在下班后试着模拟样品。
编辑:嗯,这是一个概念。如果你将匿名方法传递给属性会更聪明,但它仍然是一个进步。
在:
[DpDefault("The Void")]
[DpCoerce(new CoerceValueCallback(MainWindow.CoerceAddress))]
[DpChanged(new PropertyChangedCallback(MainWindow.ChangeAddress1))]
[DpChanged(new PropertyChangedCallback(MainWindow.ChangeAddress2))]
[DpOptions(FrameworkPropertyMetadataOptions.Inherits)]
public string Address {
get { return Dp.Get<string>(); }
set {
if (Dp.Get<string>() != value) {
Dp.Set(value);
PostOffice.SendMailToTheBoss("I moved!");
}
}
}
后:
public string Address {
get { return (string)GetValue(AddressProperty); }
set {
if ((string)GetValue(AddressProperty) != value) {
SetValue(AddressProperty, value);
PostOffice.SendMailToTheBoss("I moved!");
}
}
}
public static readonly DependencyProperty AddressProperty =
DependencyProperty.Register("Address", typeof(string), typeof(MainWindow),
new FrameworkPropertyMetadata((string)"The Void",
FrameworkPropertyMetadataOptions.Inherits,
new PropertyChangedCallback(MainWindow.ChangeAddress1)
+ new PropertyChangedCallback(MainWindow.ChangeAddress2),
new CoerceValueCallback(MainWindow.CoerceAddress)));
通常,只会使用'DpDefault'属性,但即使它不能缩短代码,它肯定会更清晰。这将是一个更典型的例子:
在:
[DpDefault("The Void")]
public string Address { get; set; }
后:
public string Address {
get { return (string)GetValue(AddressProperty); }
set { SetValue(AddressProperty, value); }
}
public static readonly DependencyProperty AddressProperty =
DependencyProperty.Register("Address", typeof(string), typeof(MainWindow),
new UIPropertyMetadata((string)"The Void"));
答案 3 :(得分:0)
可能会让你的生活变得更轻松的事情......(我从Caliburn Micro那里拿起它)。
public virtual void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property) {
NotifyOfPropertyChange(property.GetMemberInfo().Name);
}
这使您可以执行以下操作..
NotifyOfProperyChange(()=&gt; this.PropertyName);
这将突出显示设计时代码的任何问题,而不是运行时间。
Caliburn Micro是一个非常棒的小框架,你应该看看它,它消除了与MVVM和Silverlight / WPF有关的大量连线!
答案 4 :(得分:0)
这已经可以使用AOP(面向方面编程)工具完成,例如PostSharp:http://www.richard-banks.org/2009/02/aspect-oriented-programming.html(使用v1.x) http://www.sharpcrafters.com/solutions/ui#data-binding(使用v2.0)
我使用PostSharp在少数几个项目中实现INPC,效果非常好,代码更清晰,更易于维护(编译时间增加了几秒)