c# - 如何在实例化大量控件时不阻塞 UI

标签 c# wpf multithreading xaml task-parallel-library

有很多文章介绍如何在 WPF 中保持 UI 线程空闲。大多数情况下,使用 async-await 在后台执行长时间操作。但是,当 UI 生成本身很重时,我该怎么办?

假设我有一个 View 模型,它在类型为 List 的名为“Items”的属性中保存项目列表,以及一个使用绑定(bind)到该列表的 ItemsControl 呈现它们并使用数据为每个项目生成 ui 的 View 模板。我正在从服务器读取信息,在获取数据时,有某种动画“忙碌”指示器绑定(bind)到 View 模型中的 IsBusy 属性。这种方法一切都很好,它使 UI 保持响应。

一旦数据返回并完成任务,我还在后台任务中为每个项目生成可观察对象 (ItemType)(因为还没有 UI 绑定(bind)到它们,这不是问题),然后复制来自服务器的结果中的信息。仍然 - 一切都很好, react 灵敏。

最后一步必须发生在 UI 线程中。一旦 List 准备就绪,将它放在 Items 属性中会产生一个通知,使 ItemsControl 开始为每个项目生成 UI,并且这在 UI 线程上发生(并且必须发生)。由于这是一项繁重的任务(没有很多项目,但每个项目都有一个相当繁重的 UI 模板),UI 挂起并且繁忙指示器不再显示动画。

我的问题是:有没有办法在填充项目控件时保持 UI 响应?目前,这需要 0.5 到 3 秒,对于 UI 来说,这是一个太长的任务,无法保持卡住。

编辑: 只是说清楚 - 这不是关于虚拟化的问题。我对创建 View 需要很长时间没有问题,我只是想找到一种方法来在创建时保持 UI 响应。我考虑过在它隐藏甚至折叠时绘制它,但它不会改变任何东西,因为 UI 线程在执行此操作时仍然很忙,并且忙碌的动画仍然卡住,整个 UI 也会卡住。

谢谢

最佳答案

是的。不要一次绘制所有项目 - 只绘制那些您需要立即绘制的项目。这也称为 UI 虚拟化。

Microsoft 在以下链接中提供了一个很好的示例,说明如何使用 Canvas 实现虚拟化:Virtualized WPF Canvas

评论后更新:

如果隐藏面板,项目实际上会绘制到面板上但不可见。要停止项目一一显示,请将面板设置为 Visibility.Hidden,然后在绘制项目后设置为 Visibility.Visible。面板显示为空白,然后突然填充。

关于c# - 如何在实例化大量控件时不阻塞 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25626713/

相关文章:

c# - WPF 中的填充弧

java - 为什么是 "when a thread invokes d.wait, it must own the intrinsic lock for d"?

java - 我可以从构造函数启动线程吗?

c# - 为什么没有 linq for byte, uint?

c# - 升级到 EF6 破坏了 Azure 的通用提供程序 session 状态

c# - 将 Azure AD 与 Microsoft.Owin.Security.OpenIdConnect 配合使用时抛出 "IDX10223: Lifetime validation failed. The token is expired."

c# - 在什么情况下 WPF 会将键盘焦点返回到主窗口?

c# - 如何在 CustomControl 中以编程方式应用样式

java - 在 LocationOverlay 对象的 .runOnFirstFix() 方法中取消 Runnable

c# - .NET Windows 窗体设计时规则