3

我开发了很多视图模型,它们是:

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 的自动实现有意义吗?

4

5 回答 5

4

试试这个

http://code.google.com/p/notifypropertyweaver/

  • 不需要属性
  • 无需参考
  • 不需要基类

这是我关于它的博客文章

http://codesimonsays.blogspot.com/2010/11/attempting-to-solve-inotifypropertychan.html

它支持您请求的属性

  • NotifyPropertyAttribute(通知属性)
  • NotifyForAllAttribute(通知一个类型的所有属性)
  • NotifyIgnoreAttribute(不通知属性或类型)
  • AlsoNotifyFor(允许注入指向不同属性的通知代码)

尽管这些是选项并且专为微调而设计。大多数注入是通过分析现有的 IL 按照惯例完成的。

于 2010-12-01T21:20:09.207 回答
1

对于任何语言的方法、属性或变量,“魔术”几乎总是一个糟糕的名称。您应该将该属性重命名为更具描述性的名称。想象一下,你只是一个随机的互联网行人,偶然发现了一个带有“魔法”属性的代码,它告诉你关于代码的什么?完全没有:)

无论如何,我会尝试你的代码,它有可能节省很多时间。这绝对应该是 .NET 的一部分。

于 2010-12-01T17:27:06.700 回答
1

如果我们要进行花哨的代码生成,我想我更喜欢一种更容易生成 DependancyProperties 的方法。我使用的代码片段当然很有帮助,但我不喜欢当你有 on-changed 和 coerce 回调以及元数据选项时代码看起来多么混乱。也许我会在下班后尝试模拟一个样本。

编辑:嗯,这是一个概念。如果您将匿名方法传递给属性,它看起来会更聪明,但这仍然是一个进步。

前:

[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"));
于 2010-12-01T18:09:22.993 回答
0

这可能会让你的生活更轻松一点……(我从 Caliburn Micro 那里得到了它)。

 public virtual void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property) {
            NotifyOfPropertyChange(property.GetMemberInfo().Name);
        }

这使您能够执行以下操作..

NotifyOfProperyChange(() => this.PropertyName);

这将在设计时突出显示代码的任何问题,而不是在运行时。

Caliburn Micro 是一个很棒的小框架,您应该看看它,它消除了与 MVVM 和 Silverlight / WPF 相关的大量布线!

于 2010-12-01T17:16:27.487 回答
0

这已经可以使用PostSharp之类的 AOP(面向方面​​编程)工具完成: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,效果非常好,代码更加简洁和可维护(它增加了几秒钟的编译时间)

于 2010-12-01T17:29:40.713 回答