Control.VisibleChanged事件未引发

时间:2011-01-07 13:58:26

标签: .net winforms events listview

简短问题:

我注意到当Visible属性从true变为false时,不会触发Control.VisibleChanged事件。

我已经阅读了这篇文章,深入解释了Visible属性的实现方式(link)。这并没有解决我的问题,因为我直接设置了UserControl的Visible属性,而且我不会在子可见状态事件上撒谎。

我错过了什么?

长问题:

我有一个包含带有许多元素的ListView的UserControl。 ListView是使用虚拟模式实现的,因此仅在必要时才创建节点。

当相关对象发生变化时,ListView项目应自行更新;它知道何时该对象具有 ObjectChanged 事件,该事件在对象发生更改时通知订阅者。因此,在构造ListViewItem时,还要订阅MyObject.ObjectChanged事件。

可悲的是,MyObject实例在内存中几乎是持久的(从未处理过),但是虚拟模式下的ListView请求我创建大量表示同一对象的ListViewItem。由于创建的ListViewItem instanced订阅了(持久)对象,因此它们永远不会被丢弃,从而导致内存泄漏。

在对应的情况下,如果创建的ListViewItem实例没有订阅ObjectChanged事件,它们将在GC唤醒后立即处理;但这将是一个问题,因为节点不会在更改时自行更新。如果UserControl跟踪创建的ListViewItem实例,则可以采用解决方法,但这会最大程度地降低ListView在虚拟模式下的优势。

所以,我放弃了。我将跟踪每个创建的节点。

接下来,我想在UserControl不可见时重置ListViewItem集合,但是......

[参考简短问题]

1 个答案:

答案 0 :(得分:1)

不能完全遵循这个,但听起来像是一个XY问题。使用VisibleChanged很棘手,它不遵循您指定的Visible值。只有实际的可见性状态。

不要以任何方式使ListViewItems知道底层数据的更改状态。我猜你正在使用带有事件的派生类。是的,如果没有收集事件源,那将会泄漏项目。而是调用列表视图的Invalidate()方法来强制它重绘自己。它将针对任何可见项再次引发RetrieveVirtualItem事件,以便它们显示更新的数据。如果要优化此项,仅在更新可见项时调用Invalidate,然后实现CacheVirtualItems事件。