为啥 UserControl 的 Unloaded 事件不会触发?
Posted
技术标签:
【中文标题】为啥 UserControl 的 Unloaded 事件不会触发?【英文标题】:Why the Unloaded event of UserControl would not fire?为什么 UserControl 的 Unloaded 事件不会触发? 【发布时间】:2017-05-22 03:48:04 【问题描述】:我刚刚在我正在开发的一个简单的 Windows 应用商店应用中发现了一个巨大的内存泄漏。
原来我在 ListView 的ItemTemplate
中放置了一个 UserControl,并挂钩了 UserControl 的Unloaded
事件以分离一些事件处理程序。
我预计当 ListView 的项目被清除时,UserControl 的Unloaded
事件会触发,但它不会!但是当我删除一项一项时,UserControl 的Unloaded
事件将按预期触发。
有人可以给我一些建议吗?或者除了挂钩Unloaded
事件之外,我应该把清理代码放在哪里。任何想法将不胜感激!谢谢!下面是代码sn-p:
为了简化,ListView的ItemTemplate
是:
<DataTemplate>
<local:MyUserControl1 />
</DataTemplate>
而 MyUserControl1 只是一个空的 UserControl:
public sealed partial class MyUserControl1 : UserControl
public MyUserControl1()
this.InitializeComponent();
this.Unloaded += MyUserControl1_Unloaded;
private void MyUserControl1_Unloaded(object sender, RoutedEventArgs e)
Debug.WriteLine("MyUserControl1_Unloaded...");
【问题讨论】:
【参考方案1】:默认的 ListView 会启用 UI 虚拟化。当你调用Clear()
方法时,ListView 会做一些特殊处理,它实际上并没有删除这些项目(相信你也发现了这种情况)。
您可以在实时可视化树中看到 ListView 的 ActualHeight(设置为 0)。这就是你在 UI 上看不到 listview 的原因。
所以解决方法是使用Remove()
方法或listview.Itemsource=null
。您也可以尝试禁用 UI 虚拟化。例如,使用 StackPanel
作为 ItemsPanelTemplate。
【讨论】:
是的,你是对的。它是 ListView ui 虚拟化的设计机制。我将继续使用 ui 虚拟化,并找到了控制缓存大小的解决方案。这是我在 msdn 上的帖子:social.msdn.microsoft.com/Forums/en-US/… 问题依然存在。我已经尝试了这两种方法:1)一个一个地删除所有项目(而不是清除);2)让 listview.Itemsource = null。 ListView 还保留了一些项目,我希望所有项目都从内存中删除。 @SimonFisher 我参考您的 MSDN 线程上的代码进行测试。我无法重现此问题。当我调用Clear()
,Remove()
方法时,这些项目将被删除。我在 SnapShot 报告中找不到它。
我再次运行性能分析器几次,每次都得到相同的结果:内存中将保留 75 或 76 个项目(我已单击强制 GC)。仍在寻找原因。以上是关于为啥 UserControl 的 Unloaded 事件不会触发?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 UserControl 中没有正确更新 Visible 属性?
为啥我不能在我的 UserControl 中重置 TextBox 的背景?