如何遍历WPF Prism Unity目录中所有已注册模块的全部View实例
解决方案
你可以通过两种常见方案实现需求,分别适用于不同的使用场景:
方案1:遍历Prism区域管理器的所有已加载View
该方案不需要修改现有View代码,仅适用于所有目标View都是通过Prism导航机制加载到Region中的场景。
实现逻辑:
所有通过RegisterForNavigation注册的View,在被导航加载后都会被纳入Prism全局IRegionManager的管理范围,直接遍历所有Region下的View即可覆盖所有已实例化的导航页。
示例代码:
using Prism.Regions; using System.Windows; protected override void OnExit(ExitEventArgs e) { // 从Prism容器获取全局区域管理器 var regionManager = Container.Resolve<IRegionManager>(); // 递归遍历所有区域的视图 TraverseRegionViews(regionManager); base.OnExit(e); } private void TraverseRegionViews(IRegionManager regionManager) { foreach (var region in regionManager.Regions) { foreach (var view in region.Views) { // 匹配接口并调用保存方法 if (view is IAppOnExitAware exitAwareView) { exitAwareView.SaveViewSettings(); } // 处理嵌套Region场景:如果View本身挂载了子区域管理器,递归遍历 if (view is DependencyObject depObj) { var childRegionManager = RegionManager.GetRegionManager(depObj); if (childRegionManager != null && childRegionManager != regionManager) { TraverseRegionViews(childRegionManager); } } } } }
方案2:全局自动收集实现接口的View实例
该方案适用于所有场景,不管View是否通过Prism导航加载,仅需要少量代码即可实现全量实例的收集。
实现逻辑:
通过弱引用集合存储所有实现IAppOnExitAware的View实例,既不会遗漏任何符合要求的实例,也不会因为强持有导致View内存无法释放。
示例代码:
首先定义全局收集工具类:
public static class AppExitAwareCollector { // 用弱引用存储实例,避免内存泄漏 private static readonly List<WeakReference<IAppOnExitAware>> _instances = new(); private static readonly object _lockObj = new(); // 注册实例,在View构造函数中调用 public static void Register(IAppOnExitAware instance) { lock (_lockObj) { // 先清理已经被GC回收的无效实例 _instances.RemoveAll(x => !x.TryGetTarget(out _)); _instances.Add(new WeakReference<IAppOnExitAware>(instance)); } } // 全局调用所有实例的保存方法,在App退出时触发 public static void InvokeAllSave() { lock (_lockObj) { foreach (var weakRef in _instances) { if (weakRef.TryGetTarget(out var instance)) { instance.SaveViewSettings(); } } _instances.Clear(); } } }
在所有实现IAppOnExitAware的View构造函数中添加注册逻辑:
public partial class ExistingOrderView : UserControl, IAppOnExitAware { public ExistingOrderView() { InitializeComponent(); // 新增注册逻辑 AppExitAwareCollector.Register(this); } public void SaveViewSettings() { // 你的视图配置保存逻辑 } }
最后在App的OnExit方法中直接调用即可:
protected override void OnExit(ExitEventArgs e) { AppExitAwareCollector.InvokeAllSave(); base.OnExit(e); }
方案选择建议
- 如果所有目标View都是通过Prism导航加载,且不想修改每个View的代码,选择方案1
- 如果存在非导航创建的View,或者需要确保所有实现接口的实例都被触发,选择方案2
内容的提问来源于stack exchange,提问作者Alexey Titov
相关产品推荐
相关产品推荐

