我实现了一个WPF应用程序,使用NavigationService在页面之间进行导航。
当我从一个页面切换到另一个页面时,对于属于前一个页面的每个图形元素,都会引发Unloaded事件。
有没有一种方法可以取消该事件,而不需要访问图形元素,只需要访问容器?
由于Unloaded(以及Loaded)不是隧道事件,我认为没有任何方法可以在高级别上取消此操作。
我很好奇你想要实现什么。您是否正在释放与子项关联的资源?您是否担心返回此页面并重新初始化资源的影响?如果是这样,也许应用程序缓存是一个更好的存储它们的地方,这样您就可以知道它们何时被初始化,它们被使用了多少次等。这也将为您提供一个集中的地方来清理缓存的资源,在内存压力或您知道先前步骤的资源无效的情况下(例如,您已完成向导,因此您知道不需要与早期步骤相关联的任何资源)。
或者,如果您正在寻找取消导航的机会,我认为您正在寻找Navigating事件。取消此事件应该停止加载新资源并防止当前页面更改。
——添加有关缓存解决方案的信息(无法适合评论)
我的第一个想法是,只有在真实世界中确实存在性能问题时,才应该进行优化。如果这确实成为问题,您可以创建一个单例缓存对象,该对象存在于应用程序中以管理这些对象。我相信有一些我不知道的预建解决方案,但是一个包装在接口中的字符串键的字典再包装在Singeton对象中的解决方案对于简单应用程序足够。然后,您可以通过简单的接口访问它。
CustomApplicationObjectCache[CACHE_KEY_CONSTANT_STRING] = new VisualBrush(...); //Or whatever type you have
除非您处理一些非常重的对象或对象图,否则我认为缓存可能过度,并且可能会妨碍.NET执行垃圾回收的正确操作。我建议对应用程序进行分析,看看这是否实际上是您的性能问题。
Unloaded
事件在PresentationSource断开连接后触发,这是在导航到另一个页面之后发生的。
WPF非常注重确保Unloaded
事件在每个控件的PresentationSource
断开连接时都会被触发,因此防止Unloaded
事件在您的图形元素上触发的唯一方法是防止PresentationSource
被断开连接。有几种方法可以实现这一点:
解决方案1:取消导航事件
一种方法是取消Navigating
事件,强制用户停留在同一页。当然,这将防止PresentationSource
被断开连接,因此Unloaded
事件不会触发。这可能或可能不是可行的解决方案,具体取决于您的特定UI要求。
解决方案2:将元素父级放置在导航框架之外
使用AdornerLayer
,可以让导航框架之外的控件看起来像它们实际上在导航框架内部一样。由于导航框架之外的可视树在导航时不会改变,所以PresentationSource
从未与Adorner
断开连接。
解决方案3:使用自己的PresentationSource
如果您绝对必须防止图形元素被断开连接,可以实现自己的PresentationSource
。将您的图形元素放在自定义的PresentationSource
下,然后使用DrawingContext
将它们绘制到真正的PresentationSource
上。如果您希望您的控件进行交互,则还需要重定向输入事件。请注意,此解决方案非常复杂,只应作为最后的手段使用。
我在这里回答了一个类似的问题。我知道你想要实现什么。这对我总是有效的:
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