Отменить событие Unloaded в приложении WPF - PullRequest
2 голосов
/ 02 марта 2010

Я реализовал приложение WPF, которое использует NavigationService для навигации между страницами.
Когда я переключаюсь со страницы на другую, событие Unloaded возникает для каждого графического элемента, который принадлежит предыдущей странице.
Есть ли способ отменить это событие, не имея доступа к графическим элементам, а только к контейнеру?

Ответы [ 3 ]

3 голосов
/ 02 марта 2010

Поскольку Unloaded (и Loaded, в этом отношении) не являются туннельными событиями, я не думаю, что есть способ отменить это на высоком уровне.

Мне любопытно, чего вы пытаетесь достичь. Вы освобождаете ресурсы, связанные с дочерними элементами? Вы обеспокоены последствиями возврата на эту страницу и повторной инициализации ресурсов? Если это так, возможно, кеш приложений является лучшим местом для их хранения, так что вы можете определить, когда они были инициализированы, как часто они использовались и т. Д. Это также даст вам централизованное место для очистки кэшированных ресурсов в случае нехватка памяти или ситуация, когда вы знали, что ресурсы предыдущих шагов недопустимы (например, вы завершили работу мастера, поэтому вы знаете, что вам не нужны ресурсы, связанные с предыдущими шагами мастера).

С другой стороны, если вы ищете возможность полностью отменить навигацию, я думаю, вы ищете событие Navigating . Отмена этого события должна остановить загрузку нового ресурса и предотвратить изменение текущей страницы.

- Добавление информации о решении для кэширования (не помещается в комментарии)

Сначала я подумал, что вам следует оптимизировать только тогда, когда вы знаете, что на самом деле проблема с производительностью в реальном мире. Если это действительно является проблемой, вы можете создать одноэлементный объект кэширования, который живет в вашем приложении для управления этими объектами. Я уверен, что есть некоторые готовые решения, о которых я не знаю, но для простого приложения достаточно было бы словаря, обернутого в интерфейс со строковыми ключами, обернутыми в объект Singeton. Вы можете получить к нему доступ через простой интерфейс

CustomApplicationObjectCache[CACHE_KEY_CONSTANT_STRING] = new VisualBrush(...); //Or whatever type you have

Если вы не имеете дело с какими-то очень тяжелыми объектами или графами объектов, я подозреваю, что кэширование было бы излишним и, вероятно, помешало бы .NET сделать правильные вещи для сборки мусора. Я бы порекомендовал профилировать ваше приложение и посмотреть, действительно ли это проблема для вас.

2 голосов
/ 02 марта 2010

Unloaded срабатывает, когда PresentationSource отключен, то есть после того, как переход на другую страницу уже состоялся.

WPF очень внимательно следит за тем, чтобы Unloaded срабатывал на каждом элементе управления, у которого отключен PresentationSource, поэтому единственный способ предотвратить запуск Unloaded на ваших графических элементах - предотвратить отключение PresentationSource , Есть несколько способов сделать это:

Решение 1: отменить событие навигации

Один из способов сделать это - отменить событие Navigating, заставив пользователя остаться на той же странице. Это, конечно, предотвратит отключение PresentationSource, поэтому событие Unloaded не сработает. Это может или не может быть жизнеспособным решением, в зависимости от ваших конкретных требований пользовательского интерфейса.

Решение 2. Создайте родительские элементы вне рамки навигации

Используя AdornerLayer возможно, чтобы элементы управления за пределами рамки навигации выглядели так, как если бы они находились внутри рамки навигации. Поскольку визуальное дерево вне рамки навигации не изменяется во время навигации, PresentationSource никогда не отключается от Adorner.

Решение 3. Используйте собственный источник презентаций

Если вы должны полностью предотвратить отключение графических элементов, вы можете реализовать свой собственный PresentationSource. Поместите свои графические элементы под свой пользовательский PresentationSource, затем нарисуйте их на реальном PresentationSource, используя DrawingContext. Вам также может понадобиться перенаправить входные события, если вы хотите, чтобы ваши элементы управления взаимодействовали. Обратите внимание, что это решение довольно сложное и должно использоваться только в качестве крайней меры.

0 голосов
/ 29 апреля 2015

Я ответил на похожий вопрос здесь. Я точно знаю, чего ты хочешь достичь. Это всегда работает для меня:

private void UserControl_Unloaded(object sender, RoutedEventArgs e)
        {
            if (ConditionsMet) { e.Handled = true; }

            //if ConditionsMet the Unloaded event will be set to true henceforth keeping your control in the VisualTree - your control does not Unload
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...