【问题标题】:How or when to cleanup RelayCommand objects in WPF/MVVM?如何或何时清理 WPF/MVVM 中的 RelayCommand 对象?
【发布时间】:2011-11-03 00:36:53
【问题描述】:

我正在使用 RelayCommand 的标准 Josh Smith 实现在我的 WPF/MVVM 应用程序中实现 ICommand。见:WPF Apps with the MVVM Design Pattern

我的一些 CanExecute 方法需要很长时间才能运行。单独来说,它们还不错(每个只有几分之一秒)。但我注意到,绑定到 UI 的命令越多,应用程序的响应速度就越慢(延迟超过 10 秒 - 呸)。

我相信这是因为 RelayCommand CanExecuteChanged 连接到 CommandManager.RequerySuggested 事件,并且我的 ViewModel 模板调用 CommandManager.InvalidateRequerySuggested() 作为 IDataErrorInfo 验证的一部分。

我的 ViewModel 实现了 IDisposable,因此我尝试利用 OnDispose 方法来清理我的 RelayCommands,但即使在我的 VM 被处置后,ICommand.CanExecute 方法仍会继续被调用。

这使我得出结论,某些东西(CommandManager?视图?)持有对 RelayCommand 的引用。

有没有人有一个很好的模式来释放和处置 RelayCommands 以防止它们在所需的生命周期到期后被重新查询?

有没有更好的方法来管理何时应该调用 CanExecute?

【问题讨论】:

  • CanExecute 被频繁调用,因此强烈建议这是一个快速计算。如果您有更复杂的标准,我建议根据状态更改时的计算将结果缓存在字段或属性中,而不是在请求状态时。
  • 所以你的意思是,“如果这样做很痛苦,就不要这样做”。我认为这只是答案的一半。我同意 CanExecute 经常被调用并且应该快速响应。不幸的是,在处理并发时,我仍然需要查询数据库来评估 biz 规则。是的,这会产生竞争条件,但我不希望通过在客户端缓存验证结果来扩大窗口。这仍然没有回答如何在命令过期后停止对 CanExecute 的不必要调用的问题。
  • 针对您当前问题的一个建议是修改 RelayCommand 以实现 IDisposable 以便您明确地处置它,然后在处置它后忽略后续的 CanExecute 请求。不过,它仍然被调用有点奇怪。您的 View 是否仍绑定到您的(已处置的)ViewModel?
  • 我曾考虑在 RelayCommand 上实现 IDisposable,但选择扩展我的 ViewModel 基类的已实现 Dispose 方法,以便在 VM 上请求 dispose 时进行标记,并缩短 CanExecute 回调方法。跨度>
  • 至于 View 绑定到 ViewModel,我不确定 View 何时被释放。我的所有视图都作为用户控件实现并托管在选项卡控件中。当用户请求关闭选项卡时,我从数据绑定的 tabitems 的 ObservableCollection 中删除了我的 TabViewModel。我没有显式分离数据绑定,并且 UserControl 没有实现 IDisposable,所以我猜他们会在堆上徘徊等待 GC 启动。这是一个合理的假设吗?

标签: wpf mvvm relaycommand


【解决方案1】:

您可以取出CommandManager.RequerySuggested 并使用MVVM Light's RelayCommand implementation。注意:这需要您在想要更新 CanExecute 的任何时候显式调用 RaiseCanExecuteChanged()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-10
    • 2013-11-10
    • 2018-12-25
    相关资源
    最近更新 更多