You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何遍历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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 00:36:01