Os controles do Silverlight devem ser recarregados nas páginas?

Alguns meses atrás, comecei a desenvolver um aplicativo Silverlight por conta própria. Eu rapidamente descobri que não conseguia obter a coleta de lixo esperada para a maioria dos meus controles. Eu lutei por cerca de uma semana com o gerenciador de perfis de memória WinDBG e ANTS e, em seguida, encontrei o fio "DataTemplate memory leak" no fórum do Silverlight (http://forums.silverlight.net/forums/t/171739.aspx).

Dado que tantas pessoas pareciam estar frustradas com vários problemas de memória, decidi adiar mais investigações sobre a situação da memória até que o problema mais óbvio fosse resolvido.

Enfim, agora estou analisando o problema novamente e percebo que o problema que estou tendo é muito mais fundamental do que eu pensava. Eu simplesmente não tenho um paradigma para escrever controles colecionáveis de lixo do Silverlight quando: a) o controle tem propriedades de dependência que podem ser vinculadas eb) o controle pode ser descarregado de um controle e, posteriormente, carregado novamente.

Estou começando a pensar que a segunda dessas demandas é grande demais. alguém pode confirmar isso?

Para dar um pouquinho mais de detalhes, o padrão mais robusto que posso criar para escrever bons controles Silverlight colecionáveis por lixo é o seguinte:

1) Quando um modelo de controle é aplicado (na substituição OnApplyTemplate), eu configuro quaisquer ligações internas entre propriedades locais e TemplateParts. Por exemplo, eu posso configurar uma Ligação entre uma propriedade local chamada CanSearch e um botão.

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

2) Quando o controle gera o evento Unloaded, limpe as ligações internas e desconecte todos os manipuladores de eventos.

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

Essa parece ser a maneira mais limpa de garantir que não existam referências finais entre o elemento x_Button_Search e o Control. Não sei se isso é estritamente necessário.

3) Novamente, quando o Controle gera o evento Unloaded, eu limpo as ligações às propriedades de dependência existentes.

 this.ClearValue(SearchParametersProperty);

Se eu não fizer isso, posso causar vazamentos. Por exemplo, se a propriedade SearchParameters estiver vinculada a algum objeto INotifyPropertyChanged, uma referência ao Control permanecerá no evento PropertyChanged no objeto INotifyPropertyChanged ao qual estou vinculado, mesmo após o descarregamento do controle, ou seja, a View permanecerá por enquanto Modelo e isso pode não ser desejado.

4) Eu 'clico' o valor do modelo para que da próxima vez que o controle seja carregado, o modelo seja reaplicado e o método OnApplyTemplate seja acionado novamente.

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

O motivo para fazer 4 é que preciso restabelecer as ligações quando o Controle é recarregado em uma página. No Silverlight, há dois pontos de entrada pelos quais fazer isso: na substituição OnApplyTemplate ou após o controle disparar o evento Loaded. Como desejo impor valores de ligação antes do carregamento do controle (para evitar oscilações), há apenas um ponto de entrada disponível, OnApplyTemplate. Eu tenho que piscar o modelo para forçar o modelo a reaplicar quando o controle é recarregado.

Parece que esse padrão até o ponto 3 é o mínimo necessário para fornecer controles de coleta de lixo.

Meu problema surge quando você deseja descarregar seu controle (removê-lo de um painel, por exemplo) e recarregá-lo posteriormente. Quaisquer propriedades de dependência no controle foram definidas como nulas no ponto 3. Por exemplo, imagine que haja uma ligação na declaração do controle, por exemplo. . Tanto quanto posso dizer, não há como restabelecer essa associação depois que o valor de SearchParameters foi definido como nulo, afinal não faz parte de um modelo. O resultado é que, quando o controle é recarregado, é como se o valor de SearchParameters fosse nulo. Portanto, pulo a etapa 3 do padrão e obtenho um controle recarregável que não é coletado pelo lixo, ou mantenho 3 e obtenho um controle não recarregável.

questionAnswers(1)

yourAnswerToTheQuestion