Should Silverlight Controls be re

Some months ago I started developing a Silverlight application on my own. I quickly discovered that I was unable to get expected garbage collection for most of my controls. I struggled for about a week with WinDBG and ANTS memory profiler and then found the "DataTemplate memory leak" strand on the Silverlight forum (http://forums.silverlight.net/forums/t/171739.aspx).

Given that so many people seemed to be frustrated with various memory issues I decided to delay further investigation into the memory situation until the most obvious issue was resolved.

Anyway, now I'm looking into the issue again and I realise that the problem I'm having is much more fundamental than I had first thought. I simply don't have a paradigm for writing garbage collectable Silverlight controls when: a) the control has dependency properties that can be bound to, and b) the control can be unloaded from one control and then subsequently loaded again.

I'm starting to think that the second of these demands is too great. Can anyone confirm this?

To give a tiny bit more detail, the most robust pattern I can come up with for writing good, garbage collectable Silverlight controls is as follows:

1) When a Control's Template is applied (in the OnApplyTemplate override) I setup any internal bindings between local properties and TemplateParts. For example, I might setup a Binding between a local property called CanSearch and a button.

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

2) When the Control raises the Unloaded event, I clear the internal bindings and un-wire any eventhandlers.

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

This seems to be the cleanest way of ensuring that no trailing references exist between the x_Button_Search element and the Control. I don't know if this is strictly necessary.

3) Again, when the Control raises the Unloaded event, I clear bindings to existing dependency properties.

 this.ClearValue(SearchParametersProperty);

If I fail to do this I can cause leaks. For example, if the SearchParameters property was bound to some INotifyPropertyChanged object then a reference to the Control remains in the PropertyChanged event on the INotifyPropertyChanged object to which I am bound even after the control has been unloaded ie the View will stay around as long as the Model and that may not be desired.

4) I 'flicker' the Template value so that next time the control is loaded, the template is reapplied and the OnApplyTemplate method is fired again.

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

The reason to do 4 is that I need to reinstate bindings when the Control is reloaded onto a page. In Silverlight, there are two points of entry through which to do this: in the OnApplyTemplate override or after the control fires the Loaded event. As I want to enforce binding values before the control has been loaded (to avoid flickering), there is only one available entry point available, OnApplyTemplate. I have to flicker the template in order to force the template to reapply when the control is reloaded.

It appears this pattern up to point 3 is the bare minimum for providing garbage collected controls.

My problem comes when you want to unload your control (remove it from a Panel for example) and subsequently reload it. Any dependency properties on the control have been set to null in point 3. For example, imagine there is a binding on the declaration of the control eg . As far as I can tell, there is no way of reinstating this Binding once the value of SearchParameters has been set to null, it's not part of a Template after all. The result is that when the control is re-loaded it's as if the value of SearchParameters was null. So I either skip out step 3 in the pattern and get a reloadable control that is not garbage collected, or I keep 3 and get an unreloadable control.


What you do in 1) seems really strange. Why initiating a binding to the template in code and not in xaml? We have solved lots of memory leak issues in silverlight using this software

http://memprofiler.com/

EDIT

For more control over the binding, you can use

{Binding Property, RelativeSource={RelativeSource TemplatedParent}}

That way the implicit converters are used as expected and you can also specify your own. And I believe that BindingMode TwoWay works as well. Good luck!

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

上一篇: 学习Silverlight 4数据绑定的基础知识

下一篇: 应该重新Silverlight控件