数百个自定义用户控件创建了数千个用户对象。

5
我正在创建一个仪表盘应用程序,该应用程序在 FlowLayoutPanel 上显示数百个“项目”。
每个“项目”都是由 12 个文本框或标签组成的 UserControl
我的应用程序查询数据库,然后为每个记录创建一个“项目”实例,在将其添加到 FlowLayoutPanel 之前使用数据填充标签和文本框。
在向面板添加约 560 个项目后,我注意到任务管理器中的 USER Objects 计数已经上升到约 7300,这比我的机器上任何其他应用程序都要大得多。
我发现 560 * 13(12 个标签加上 UserControl 本身)是 7280。所以突然间我知道了所有对象的来源...
知道 Windows 在放弃之前有 10,000 个 USER 对象限制,我正在尝试找到更好的方法将这些“项目”绘制到 FlowLayoutPanel 上。
我目前的想法如下:
1. 使用 graphics.DrawTextDrawImage 替代许多标签,用户绘制“项目”。我希望这意味着 1 个“项目” = 1 个 USER Object,而不是 13 个。
2. 有一个“项目”的实例,然后对于每个记录,填充实例并使用 Control.DrawToBitmap() 方法来获取图像,然后在 FlowLayoutPanel(或类似)中使用它。
所以... 有没有其他建议?
附注:这是一个可缩放的界面,因此我已经排除了“分页”的可能性,因为需要一次查看所有项目。
3个回答

2
至少来说,我会从你的第一个想法开始。这确实可以将应用程序占用的窗口数量减少13倍。
关于你的第二个想法,如果你将 Bitmap 放入 PictureBox(或其他控件)中,从而在表单上拥有大量 PictureBox 控件,那么这并不会真正帮助你(这甚至可能更糟,因为位图有时由比通用 RAM 更有限的资源组成,这是与消耗太多窗口完全不同的问题)。只有当您将生成的位图复制到单个较大的控件上(然后处理位图)时,这才是一个好主意。
如果采用后一种方法,则无需利用渲染到控件、获取控件的位图副本,然后将该位图绘制到最终控件的中间步骤。更明智的做法是直接将用于渲染控件的代码/逻辑直接渲染到最终(多元素)控件中。

与创建数百个位图或图片框不同,我认为更好的方法是直接将每个控件绘制到单个PictureBox的图像上,或者有一个单独的“精灵”位图,并将所有控件绘制到该位图上。虽然如果它们真的只是标签,那么使用TextRenderer并完全绕过控件可能更容易 - 很难确定需要绘制什么。 - Aaronaught
我会建议他避免使用TextRenderer,因为相对于Graphics.DrawString它的速度较慢。但除此之外,我同意他的最佳方法就是直接将每个数据库行呈现到单个控件上(最好只呈现可见的行)。 - MusiGenesis

1

我建议采用您的第二个想法。这正是列表和网格控件用于显示数千条记录并能够执行原地编辑的方式。您从一个控件开始,然后将其移动到需要的任何位置。

如果您需要同时显示多个实例,则会比较困难 - 正如您提到的,您最有可能需要使用DrawToBitmap并显示控件的“幽灵图像”。

或者,我想这里正在进行一些滚动操作(毕竟谁能一次看到7280个UI对象呢?),因此您可以动态创建仅实际在屏幕上同时显示的实例。您需要计算可见区域并将其与要显示的控件列表进行比较,并且如果UI缩小得无法看清任何细节,则只显示占位符。我想,如果您这样做,滚动/缩放将成为相当消耗CPU的操作;最好根本不创建它们。


1

我已经成功地实现了#1。

用户对象减少了13倍,而且感觉更快、更响应。

感谢您的建议 - 我很惊讶这不是一个更常见的问题!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接