CommandManager 的 WPF 性能问题

标签 wpf wpf-controls binding

我们从头开始创建了一个新的、相当复杂的 WPF 应用程序,但随着使用 CommandManager 注册的命令数量增加,我们遇到了性能问题。我们在我们的 MVVM 实现中使用了简单的轻量级命令,但是我们使用的第三方控件(Infragistics)没有,并且可以自由地调用 CommandManager.RegisterClassCommandBinding 来添加 RoutedCommands。当响应用户输入时,性能问题表现为 UI 中的感知迟缓,例如控件之间的选项卡很慢,文本输入“生涩”,弹出动画“笨拙”。当应用程序第一次启动时,用户界面非常活泼。随着打开更多包含 Infragistics 网格的屏幕,性能会下降。

在内部,CommandManager 有一个名为 _requerySuggestedHandlers 的私有(private)字段,它是一个 List。我使用反射来获取对这个集合的引用,并且我注意到当我调用 .Clear() 时,UI 的响应能力会恢复到其初始状态。显然,我不想去清理我不太了解的集合,尤其是使用反射(!),但我这样做是为了看看它是否能解决性能问题,瞧,它确实做到了。

通常,这种情况会在经过一定时间后自行清理。但是,WeakReferences (_requerySuggestedHandlers) 的收集只会在垃圾收集启动后被修剪,这是不确定的。因此,当我们关闭包含网格的窗口 (Infragistics XamDataGrid) 时,“死”网格命令的 CanExecute 属性会在窗口关闭很久之后继续进行不必要的评估。这也意味着,如果我们关闭多个窗口,在启动垃圾收集之前,性能仍然很慢。我知道这可能在分配时发生,而且我自己也看到过,因为如果我打开另一个窗口,这会导致初始内存(来自已处理的 Windows)被收集并且性能恢复正常。

因此,鉴于上述情况,这是我的问题:

  • 如何以及从何处调用 CommandManager.InvalidateRequerySuggested()?我在 MSDN 上没有找到任何详细解释这一点的文档。我连接到 CommandManager.RequerySuggested 事件,看起来只要控件失去焦点就会调用它。
  • 是否可以抑制 CommandManager.InvalidateRequerySuggested() 响应用户输入而被调用?
  • 有没有其他人遇到过这个问题,如果有,你是如何避免的?

  • 谢谢!

    最佳答案

    这听起来像是确定性调用 GC.Collect() 的罕见情况之一。是正确的做法。反对它的普通论点是垃圾收集器比你更聪明。但是当你处理 WeakReference对象,你进入了你可能知道垃圾收集器不知道的东西的领域。启动垃圾收集肯定比清除 _requerySuggestedHandlers 更好。 - 除其他外,它不会对 WeakReference 做任何事情指向仍然存在的控件的对象。

    我会选择这个而不是试图弄清楚如何抑制 RequerySuggested ,因为这会破坏您仍然关心的那些命令的行为。

    关于CommandManager 的 WPF 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5144352/

    相关文章:

    c# - 由于大小写不同,WPF Combobox 在 ItemSource 中找不到 SelectedValue

    R:数字向量在日期的 cbind 后变为非数字

    wpf - WPF-默认按钮无法按预期工作

    c# - WPF旋转按钮

    c# - INotifyPropertyChanged 奇怪的 NullReferenceException

    wpf - WPF Path 对象中的属性或数据触发器

    wpf - 如何刷新循环内设置的可视控件属性 (TextBlock.text)?

    WPF ComboBox 和 SelectedItem 绑定(bind)到 XML 数据源

    wpf - 如何隐藏 WPF 控件的一部分

    c# - WCF CustomBinding - 无法使用自定义授权策略获取元数据