棱镜区域不处理视图或视图模型

本文关键字:视图 模型 处理 区域 棱镜 | 更新日期: 2023-09-27 18:10:41

我假设Prism Regions将自动检测并调用Dispose实现IDisposable接口的任何视图或视图模型。事实证明我错了。

然后我考虑实现IActiveAware,这样我就可以自己处理我的视图/视图模型,但这似乎相当粗俗。我宁愿让它自动完成。

我如何配置Prism区域来自动处理实现IDisposable的视图和视图模型?

棱镜区域不处理视图或视图模型

在互联网上广泛搜索后,没有找到任何真正的解决方案,我开发了自己的自定义RegionBehavior,结果工作得非常好。

该行为监听区域视图集合的任何更改,当任何被删除时,它检查并调用视图和/或视图模型上的Dispose,只有当它们实现IDisposable时。

class DisposeClosedViewsBehavior : RegionBehavior
{
    protected override void OnAttach()
    {
        Region.Views.CollectionChanged += Views_CollectionChanged;
    }
    private void Views_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action != NotifyCollectionChangedAction.Remove) return;
        foreach (var removedView in e.OldItems)
        {
            IDisposable disposableView = removedView as IDisposable;
            IDisposable disposableViewModel;
            var iviewView = removedView as IView;
            if (iviewView != null)
            {
                disposableViewModel = iviewView.DataContext as IDisposable;
            }
            else
            {
                var frameworkElementView = removedView as FrameworkElement;
                disposableViewModel = frameworkElementView?.DataContext as IDisposable;
            }
            disposableView?.Dispose();
            disposableViewModel?.Dispose();
        }
    }
}

最后一步是通过覆盖引导程序ConfigureDefaultRegionBehaviors方法将此行为插入prism:

protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()
{
    var factory = base.ConfigureDefaultRegionBehaviors();
    factory.AddIfMissing(nameof(DisposeClosedViewsBehavior), typeof(DisposeClosedViewsBehavior));
    return factory;
}

工作像一个魅力!

修改了Nathan A对Prism 6的回答(删除了IView),并使用了一个方便的内置助手方法来调用Dispose和ViewModel。

class DisposeClosedViewsBehavior : RegionBehavior
{
    protected override void OnAttach() =>
        Region.Views.CollectionChanged += Views_CollectionChanged;
    private void Views_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (!(e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Replace))
            return;
        foreach (var removedView in e.OldItems)
            MvvmHelpers.ViewAndViewModelAction<IDisposable>(removedView, d => d.Dispose());
    }
}