【问题标题】:MVVM - RaisePropertyChanged turning code into a messMVVM - RaisePropertyChanged 将代码变成一团糟
【发布时间】:2011-02-02 22:06:21
【问题描述】:

MVVM 新手,请原谅我的无知。

我认为我使用它是正确的,但我发现我的 ViewModel 有太多这些:

RaisePropertyChanged("SomeProperty")

每次我设置一个属性时,我都必须提升那个该死的属性改变。

我想念我可以去的日子:

public int SomeInteger { get; private set;}

这些天我不得不在任何地方都贴上“RaisePropertyChanged”,否则我的 UI 不能反映这些变化:(

是我做错了还是其他人对过多的魔术字符串和老式的属性设置器感到恼火?

我应该改用依赖属性吗? (我怀疑这无论如何都会帮助代码膨胀)

尽管存在这些问题,但我仍然认为 MVVM 是要走的路,所以我想这就是。

【问题讨论】:

  • “我想念我可以去的日子”我们多么容易忘记,在 C#2 中你根本无法做到这一点。 ;)
  • 是的,我想我被宠坏了,但尽管取得了进展,但我仍然认为可能有一种更清洁的方式来实现这些东西。虽然我不太了解内部工作/权衡......

标签: silverlight silverlight-3.0 mvvm


【解决方案1】:

看看这个What is the best or most interesting use of Extension Methods you've seen?

它描述了我的 Model 和 ViewModel 类用来启用以下强类型(无魔法字符串)属性的扩展方法和帮助方法。

private string _name;
public string Name
{
    get { return _name; }
    set { this.NotifySetProperty(ref _name, value, () => this.Name); }
}

这和我想的一样简单。希望对您有所帮助。

【讨论】:

  • 谢谢。很高兴知道我不是唯一一个有问题的人。
【解决方案2】:

您可以使用 PostSharp 的 NotifyPropertyChanged 属性。然后,您所要做的就是在类上放置一个属性,仅此而已。例如:

[NotifyPropertyChanged]
public class MyClass 
{
    public string MyProperty { get; set; }
}

【讨论】:

  • 没有运行时开销,因为 PostSharp 只是修改已编译的类并注入与您手动编写的完全相同的代码。构建时间开销很小,但我发现它可以忽略不计。
  • 这种方法的唯一缺点是,有时需要为调用 setter 的属性以外的属性设置 RaisePropertyChanged。
  • 免责声明:PostSharp 是商业软件,入门(免费)版不支持此属性。
  • 使用高级且免费的替代方案:Stepen Cleary 的计算属性。 github.com/StephenCleary/CalculatedProperties/blob/master/… 我在生产中都使用过,它比 PostSharp 的方面灵活得多。没有任何 postharp 限制适用于计算属性。它可以将依赖关系从循环、虚拟方法、LINQ 连接到对象,基本上任何你可以想象的疯狂的运行时依赖关系都不管多么间接,依赖关系图在运行时重新连接自身,并且无需任何仪式即可工作。他们也很快。样板代码也很少。
【解决方案3】:

它有助于从不同的角度看待事物:这些不是复杂的 .NET 属性,而是简化的依赖属性。

WPF 中视图模型的可绑定属性与 .NET 属性不同,它是一种键值存储。如果你想要轻量级的 DependencyObject 替代品,你有能力实现这个键值存储,只需购买在 setter 中调用某些函数 - 实际上还不错。当然,也远非理想,但你的观点肯定是不公平的。

【讨论】:

    【解决方案4】:

    它不会让您回到干净的代码,但我使用简单的扩展方法来获取属性名称以避免魔术字符串出现问题。它还保持代码的可读性,即明确发生了什么。

    扩展方法简单如下:

    public static string GetPropertyName(this MethodBase methodBase)
    {
        return methodBase.Name.Substring(4);
    }
    

    这意味着您的属性集可以抵御名称更改,如下所示:

    private string _name;
    public string Name
    {
        get { return _name; }
        set 
        {
                name = value;
                RaisePropertyChanged(MethodBase.GetCurrentMethod().GetPropertyName()); 
        }
    }
    

    我已经写了更多关于这个extension method herepublished a matching code snippet here

    【讨论】:

    • 老问题,我知道 :) 另一种方法是将 RaisePropertyChanged 封装在基类中并使用以下方法签名:OnRaisePropertyChanged([CallerMemberName] propertyName = "")。这样就可以调用方法而不需要写属性名
    【解决方案5】:

    这将有助于: “某种魔法” 轻松 INotifyPropertyChanged

    [http://visualstudiogallery.msdn.microsoft.com/d5cd6aa1-57a5-4aaa-a2be-969c6db7f88a][1]

    作为将其添加到一个属性的示例:

    [Magic] 
    public string Name { get { return _name; } set { _name = value; } } 
    string _name;
    

    将它添加到所有类属性的另一个示例:

    [Magic] 
    public class MyViewModel: INotifyPropertyChanged 
    { 
      public string Name { get; set; } 
      public string LastName { get; set; } 
      ..... 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-22
      • 1970-01-01
      • 2016-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-14
      相关资源
      最近更新 更多