Silverlight 控件是否应该重新加载到页面上?

2024-04-03

几个月前,我开始自己开发 Silverlight 应用程序。我很快发现我的大多数控件无法获得预期的垃圾回收。我在 WinDBG 和 ANTS 内存分析器上苦苦挣扎了大约一周,然后在 Silverlight 论坛 (http://forums.silverlight.net/forums/t/171739.aspx) 上发现了“DataTemplate 内存泄漏”问题。

鉴于这么多人似乎对各种内存问题感到沮丧,我决定推迟对内存情况的进一步调查,直到最明显的问题得到解决。

不管怎样,现在我再次研究这个问题,我意识到我遇到的问题比我最初想象的要根本得多。在以下情况下,我根本没有编写可垃圾收集的 Silverlight 控件的范例:a) 控件具有可绑定的依赖属性,b) 控件可以从一个控件中卸载,然后再次加载。

我开始认为第二个要求太大了。谁能证实这一点吗?

为了提供更多细节,我可以想出的用于编写良好的、可垃圾收集的 Silverlight 控件的最强大的模式如下:

1)当应用控件的模板时(在 OnApplyTemplate 覆盖中),我设置本地属性和 TemplatePart 之间的任何内部绑定。例如,我可能会在名为 CanSearch 的本地属性和按钮之间设置绑定。

if (x_Button_Search != null)
            {
                Binding b = new Binding("CanSearch");
                b.Source = this;
                this.x_Button_Search.SetBinding(Button.IsEnabledProperty, b);
            }

2)当控件引发 Unloaded 事件时,我清除内部绑定并取消连接任何事件处理程序。

if (x_Button_Search != null)
            {
                this.x_Button_Search.ClearValue(Button.IsEnabledProperty);
            }

这似乎是确保 x_Button_Search 元素和 Control 之间不存在尾随引用的最简洁方法。我不知道这是否是绝对必要的。

3) 同样,当控件引发 Unloaded 事件时,我清除与现有依赖属性的绑定。

 this.ClearValue(SearchParametersProperty);

如果我不这样做,我可能会导致泄漏。例如,如果 SearchParameters 属性绑定到某个 INotifyPropertyChanged 对象,则即使在卸载控件后,对控件的引用仍保留在我所绑定的 INotifyPropertyChanged 对象上的 PropertyChanged 事件中,即,只要模型,这可能不是所希望的。

4) 我“闪烁”Template 值,以便下次加载控件时,重新应用模板并再次触发 OnApplyTemplate 方法。

var oldTemplate = this.Template;
            this.Template = null;
            this.Template = oldTemplate;

执行 4 的原因是当控件重新加载到页面上时我需要恢复绑定。在 Silverlight 中,有两个入口点可以执行此操作:在 OnApplyTemplate 重写中或在控件触发 Loaded 事件之后。由于我想在加载控件之前强制执行绑定值(以避免闪烁),因此只有一个可用的入口点:OnApplyTemplate。我必须闪烁模板,以便在重新加载控件时强制重新应用模板。

看来第 3 点之前的这种模式是提供垃圾收集控件的最低限度。

当您想要卸载控件(例如从面板中删除它)并随后重新加载它时,我的问题就出现了。在第 3 点中,控件上的任何依赖属性都已设置为 null。例如,假设控件的声明上有一个绑定,例如。据我所知,一旦 SearchParameters 的值设置为 null,就无法恢复此绑定,毕竟它不是模板的一部分。结果是,当重新加载控件时,SearchParameters 的值就好像为 null。因此,我要么跳过模式中的第 3 步并获得一个不会被垃圾回收的可重新加载控件,要么保留第 3 步并获得一个不可重新加载的控件。


你在 1) 中所做的事情看起来很奇怪。为什么在代码中而不是在 xaml 中启动对模板的绑定? 我们使用该软件解决了 silverlight 中的许多内存泄漏问题

http://memprofiler.com/ http://memprofiler.com/

EDIT

为了更好地控制绑定,您可以使用

{Binding Property, RelativeSource={RelativeSource TemplatedParent}}

这样,隐式转换器就会按预期使用,您也可以指定自己的转换器。我相信 BindingMode TwoWay 也能工作。 祝你好运!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Silverlight 控件是否应该重新加载到页面上? 的相关文章

随机推荐