【问题标题】:Avoiding Duplicate RaisePropertyChanged for Cascading Read-Only Properties避免级联只读属性的重复 RaisePropertyChanged
【发布时间】:2023-03-22 00:00:02
【问题描述】:

我的视图模型中有几个由视图引用的只读属性,其中一些依赖于一个/多个其他只读属性(在同一视图模型中),这些属性最终依赖于一个/多个读/写属性(在同一个视图模型中)。我只在示例中看到了以下模式,以确保为所有可能受影响的属性引发 PropertyChanged 事件,但我不喜欢复制所有这些 RaisePropertyChanged 调用。

我怀疑我应该将一个处理程序添加到我的视图模型的 PropertyChanged 事件中,并且在该处理程序中,对于每个具有依赖属性的属性,仅在 直接的属性上调用 RaisePropertyChanged (相对于那些间接)依赖于该属性。如何避免重复所有这些 RaisePropertyChanged 调用?

public bool MyReadOnlyPropertyAA1
{
    get
    {
        return MyReadOnlyPropertyA1 [&& MyReadOnlyPropertyB1 ...]
    }
}


public bool MyReadOnlyPropertyA1
{
    get
    {
        return (MyPropertyA == (Some Value)) [&& MyPropertyB == (Some Other Value)) ... ]
    }
}

public MyPropertyAType MyPropertyA
{
    get
    {
        return myPropertyA
    }
    set
    {
        myPropertyA = value;
        RaisePropertyChanged(nameof(MyPropertyA));  
        RaisePropertyChanged(nameof(MyReadOnlyPropertyA));
        RaisePropertyChanged(nameof(MyReadOnlyPropertyA1));
        RaisePropertyChanged(nameof(MyReadOnlyPropertyAA1));
        ...
        RaisePropertyChanged(nameof(MyReadOnlyPropertyAA...1));
    }
}


public MyPropertyBType MyPropertyB
{
    get
    {
        return myPropertyB
    }
    set
    {
        myPropertyB = value;
        RaisePropertyChanged(nameof(MyPropertyB));  
        RaisePropertyChanged(nameof(MyReadOnlyPropertyA));
        RaisePropertyChanged(nameof(MyReadOnlyPropertyA1));
        RaisePropertyChanged(nameof(MyReadOnlyPropertyAA1));
        ...
        RaisePropertyChanged(nameof(MyReadOnlyPropertyAA...1));
    }
 }

【问题讨论】:

  • 触发只读属性的属性更改事件是愚蠢的高度。如果你给代码的用户一个属性是只读的印象,让它保持这种状态。设计不应该改变其他一些属性对其产生影响
  • @MickyD 仅仅因为属性是只读的,并不意味着该属性的值是恒定的。这只是意味着你不能通过他们的 setter 修改属性。
  • @MickyD 为什么,只是为了获取一些信息(例如,连接两个字符串,或者一个简单的计算),一个方法并没有多大帮助。拥有属性可以让您轻松绑定派生信息。
  • 不知道为什么你会得到一堆反对票,但我最好的猜测是“What are some / is the best way...”这行。这里的人们有时会过于字面地理解这种方式,并将其视为“要求列出事物”,因此因过于宽泛而反对。我建议您提出更具体的核心问题,例如 “如何避免在属性设置器中重复 RaisePropertyChanged 调用?”。就我个人而言,我不认为这是一个坏问题,而且是我早年在 SO 上可能会问的一个问题。
  • @Rachel:谢谢!我进行了编辑。显然,在 SO 上,“问起来(确实)很痛!”。嘘!

标签: c# mvvm viewmodel inotifypropertychanged


【解决方案1】:

我根据属性关系使用这两种方法。

如果更改一个属性会触发另一个属性的更改是合乎逻辑的,我只需将属性更改代码留在 setter 中。

public string PropertyA
{
    get { return propertyA; }
    set
    {
        myPropertyA = value;
        RaisePropertyChanged(nameof(PropertyA));  
        RaisePropertyChanged(nameof(IsPropertyAValid));
        ...
    }
}

但是,如果这两个属性在逻辑上不相关,那么我将使用 PropertyChange 处理程序:

private void MyClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    switch(e.PropertyName)
    {
        case "PropertyA":
            RaisePropertyChanged(nameof(PropertyB));
            break;
    }
}

这样做的原因是我不想在我的属性设置器中使用特殊逻辑。对我来说,它们应该是相当通用的,卡在#region 标签中,然后折叠起来被遗忘。

如果两个属性在逻辑上相关并且您希望更改一个可能会改变另一个的值,那么RaisePropertyChange 代码可以留在设置器中。

但是,如果它们不同,并且将来我自己或其他开发人员正在查看代码并且可能不知道/理解两者之间存在依赖关系,我会将更改放在类的 PropertyChange 事件处理程序中,这样很容易必要时查找和/或更改。

【讨论】:

  • 首先,叹息,对不起,恕我直言,这是一个值得尊敬的答案。我认为 Downvotes 应该保留给恶意不好的问题、评论和答案。否则,让缺乏/更少的赞成票为自己说话(即正面强化与负面强化)。我会推迟将其标记为答案,看看我是否得到其他答案。 FWIW,我投了赞成票,所以它会抵消至少一个(希望只是过去/未来的)反对票。
  • 再想一想,如果只读属性仅从读/写属性中删除了 1 级(如您的示例中所示),那么无论是否完成,它都是相同的 RaisePropertyChange 调用数读/写属性的设置器或属性更改事件处理程序。当只读属性被删除 2+ 级别时,在读/写属性设置器中这样做会引入重复。这些是我要问的场景。
  • 正如我之前对我的 Q 的评论中提到的那样,除了避免重复之外,将 Dependent 属性的 RaisePropertyChange 移到属性的 Setter 之外的另一个原因是为了避免什么,恕我直言,是一个问题(称为 SoC 或其他),其 PropertyChanged 事件正在被引发的属性是“依赖”而不是“依赖”的属性的“依赖”。这些属性不应该知道它们的“依赖项”是什么,就像 ViewModel 属性不应该知道视图元素依赖于它们一样。您对此有何看法?
  • @Tom 在这种情况下,只需使用 PropertyChanged 事件处理程序来监听依赖属性的更改,并根据需要引发相关的更改通知。
  • 我尝试编辑您的答案,以包括避免重复 RaisePropertyChange 调用的用例,当只读属性从被引用的读/写属性中删除 2+ 级别时,但编辑被拒绝.如果您愿意编辑您的答案以包含它,我会接受它作为答案。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-07
  • 2017-10-07
  • 1970-01-01
相关资源
最近更新 更多