应该重新Silverlight控件

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

鉴于如此多人似乎对各种记忆问题感到沮丧,我决定推迟对记忆状况的进一步调查,直到最明显的问题得到解决。

无论如何,现在我正在重新审视这个问题,并且我意识到我遇到的问题远比我第一次想到的要重要得多。 在下列情况下,我根本没有编写垃圾收集Silverlight控件的范例:a)控件具有可以绑定到的依赖项属性; b)控件可以从一个控件中卸载,然后再次加载。

我开始认为这些要求中的第二个太好了。 任何人都可以确认吗?

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

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

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

2)当Control引发Unloaded事件时,我清除内部绑定并断开任何事件处理程序的连线。

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

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

3)再次,当Control引发Unloaded事件时,我清除绑定到现有的依赖项属性。

 this.ClearValue(SearchParametersProperty);

如果我没有做到这一点,我可以造成泄漏。 例如,如果SearchParameters属性绑定到某个INotifyPropertyChanged对象,那么即使在控件已卸载后,对该控件的引用仍保留在我绑定到的INotifyPropertyChanged对象的PropertyChanged事件中,即视图将保留在模型和可能不需要。

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

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

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

看起来这种直到第3点的模式是提供垃圾收集控制的最低限度。

当您想要卸载控件(例如将其从面板中移除)并随后重新加载时,我会遇到问题。 在控制点上的任何依赖属性在第3点都被设置为null。例如,假设控制的声明有一个绑定,例如。 据我所知,一旦SearchParameters的值被设置为null,没有办法重新绑定这个绑定,毕竟它不是Template的一部分。 结果是,当控件重新加载时,就好像SearchParameters的值为null。 所以我要么跳过模式中的第3步,并获得一个没有垃圾回收的可重新加载的控件,或者我保持3并获得一个无法加载的控件。


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

http://memprofiler.com/

编辑

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

{Binding Property, RelativeSource={RelativeSource TemplatedParent}}

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

链接地址: http://www.djcxy.com/p/22781.html

上一篇: Should Silverlight Controls be re

下一篇: Why are Silverlight ContentControls not garbage collected?