【问题标题】:Pass Action instead of hooking PropertyChanged?通过 Action 而不是挂钩 PropertyChanged?
【发布时间】:2013-11-12 15:06:02
【问题描述】:

在我目前的项目中,我遇到了以下情况:

  • VM1 用于显示在屏幕上。
  • VM1 具有 VM2 的公共属性。
  • VM1 具有 VM3 的公共属性。
  • VM3 有一个依赖于 VM2 的属性。
  • VM1 没有处理机制。

一开始我考虑挂钩到 VM2.PropertyChanged 事件来检查我想要的属性并相应地更改 VM3 受影响的属性,如:

public class VM1 : INotifyPropertyChanged
{
    public property VM2 VM2 { get; private set; }
    public property VM3 VM3 { get; private set; }

    public VM1()
    {
        this.VM2 = new VM2();
        this.VM3 = new VM3();
        this.VM2.PropertyChanged += this.VM2_PropertyChanged;
    }

    private void VM2_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        // if e.PropertyName equals bla then VM3.SomeProperty = lol.     
    }
}

这意味着,由于我无法在此类中取消挂钩事件,因此存在内存泄漏。

所以我最终将一个 Action 传递给 VM2,以便在其重要属性更改值时调用它,如下所示:

public class VM2 : INotifyPropertyChanged
{
    public Action WhenP1Changes { get; set; }

    private bool _p1;
    public bool P1
    {
        get
        {
            return _p1;
        }
        set
        {
            _p1 = value;
            this.WhenP1Changes();
            this.PropertyChanged(this, new PropertChangedEventArgs("P1");
        }
    }
}

public class VM1 : INotifyPropertyChanged
{
    public VM2 VM2 { get; private set; }
    public VM3 VM3 { get; private set; }

    public VM1()
    {
        this.VM2 = new VM2();
        this.VM3 = new VM3();
        this.VM2.WhenP1Changes = () => VM3.SomeProperty = "lol";
    }
}

我这里有内存泄漏吗?

PD:如果您还可以回答以下问题,那就太好了: - 这甚至是一个好习惯吗?

谢谢

【问题讨论】:

  • “VM3 有一个依赖于 VM2 的属性” => 听起来这就是问题开始的地方。问题中的所有内容都很抽象,但这听起来是错误的。你不能重构让所有虚拟机只依赖于它们的模型吗?
  • 好吧,假设 VM2.IsEnabled 将修改 VM3.IsVisible。我接受这种依赖。

标签: c# wpf mvvm action propertychanged


【解决方案1】:

我这里有内存泄漏吗?

分配给VM2.WhenP1Changes 的lambda 捕获this VM1 实例(需要访问VM3 属性),因此只要视图模型VM2 处于活动状态,它就会保持VM1 处于活动状态。这是否最终成为泄漏取决于这些视图模型的生命周期,但其含义实际上与您使用事件的第一个示例相同。

【讨论】:

  • 感谢您对 Actions 范围和生命周期的澄清,这正是我所寻找的 :)
【解决方案2】:

简而言之,我更喜欢使用delegate 在视图模型之间进行通知。如果您有一个可以访问各种子视图模型的父视图模型(您似乎可以),那么您可以使用一个或多个 delegates 类似事件在需要更新时相互通知。

与其再次输入整个场景,我更愿意向您指出我对Passing parameters between viewmodels 问题的回答,该问题提供了该技术的完整描述和代码示例。

还有一个您可能感兴趣的补充内容,可以在我对If necessary, how to call functions in MainViewViewModel from other ViewModels 问题的回答中找到。如果您有任何问题,请告诉我。

【讨论】:

  • 基本上,您建议坚持使用基于事件的专业解决方案,您可以准确地通知发生的事情,而不是使用通用的“PorpertyChanged”事件,对吧?
  • 我倾向于使用delegates,因为我可以定义最适合当前情况的参数。但是,我认为您当前的情况不会给您带来内存泄漏,因为您的 VM2VM3 对象似乎总是存在的。只有当不再需要的对象通过对另一个对象的硬引用而保持活动状态时,才会发生内存泄漏。
  • 好吧,我非常反对直接使用代表。尽管 Action 或 Func 是委托,但它们的用法对我来说更清楚,因为需要更少的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-15
  • 2019-05-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多