Я знаю, что встроенный код предпочтительнее, но есть куча кода, который необходим, чтобы показать, что проблема действительно возникает (например, обнаружение утечки). Проект можно скачать здесь:
http://www.filefactory.com/file/c40b856/n/TestPopupLeak.zip
Вот что происходит:
По какой-то причине всплывающее окно, использующее TiltEffect, вызывает утечку последнего экземпляра (я думаю, последнего потомка). Я создал небольшое приложение POC, которое показывает это.
В этом (самом маленьком репродукции, который мне удалось создать) вы делаете следующее:
- Нажмите кнопку на экране - это просто кнопка на странице.
---> Появится другая кнопка (эта кнопка во всплывающем окне)
- Нажмите вторую кнопку, которая только что появилась
----> Вторая кнопка исчезнет.
Повторите шаги 1 и 2 несколько раз.
Несколько раз нажмите на заголовок страницы (это вызывает GC.Collect ()).
Посмотрите на окно вывода - вы увидите, что один экземпляр Grid и один экземпляр MyUserControl протекают.
Мне кажется, что последний экземпляр хранится в памяти.
Если вы удалите эффект наклона из всплывающего окна (закомментируйте строки, которые вызывают TiltEffect), вы увидите, что экземпляры освобождаются (окно вывода сообщит вам, что никакие ссылки еще не находятся в памяти).
Понятия не имею, почему это происходит ... Попытка отладки в TiltEffect и похоже, что все события отключены.
Вот код, который вызывает всплывающее окно и скрывает его (остальная часть кода обрабатывает утечки памяти и тупой пользовательский элемент управления):
public partial class MainPage : PhoneApplicationPage
{
Popup popup;
Grid grid;
// Constructor
public MainPage()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
// This creates a Popup with a MyUserControl in it (wrapped in a grid).
// MyUserControl just contains a single button that when pressed calls the .action
// member.
popup = new Popup();
InstanceTracker.DebugAddObject(popup);
grid = new Grid() { Width = 400, Height = 400 };
// This tracks memory leaks and will output every 10 seconds what objects are
// still alive.
InstanceTracker.DebugAddObject(grid);
MyUserControl control = new MyUserControl();
control.action = () => button_Click(null, null);
InstanceTracker.DebugAddObject(control);
grid.Children.Add(control);
// Comment out this line and the one below that has a similar comment
// to make the bug go away.
Microsoft.Phone.Controls.TiltEffect.SetIsTiltEnabled(grid, true);
// That's it, show the popup.
popup.Child = grid;
popup.IsOpen = true;
}
void button_Click(object sender, RoutedEventArgs e)
{
// Disable the tilt and close the popup. Get rid of roots.
// Comment this out to make the problem go away.
Microsoft.Phone.Controls.TiltEffect.SetIsTiltEnabled(popup, false);
popup.IsOpen = false;
popup = null;
grid = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
private void PageTitle_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
// Collects all memory.
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}