棱镜区域不处理视图或ViewModel

时间:2015-09-01 18:59:37

标签: c# .net wpf mvvm prism-5

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

然后我考虑实现IActiveAware所以我可以自己处理我的观点/视图模型,但这似乎相当hackish。我宁愿自动完成它。

如何配置Prism Regions以自动处理我的视图并查看实现IDisposable的模型?

2 个答案:

答案 0 :(得分:7)

在互联网上进行了广泛的搜索,并没有找到任何真正的解决方案后,我开发了自己的自定义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;
}

像魅力一样!

答案 1 :(得分:3)

修改Nathan A对Prism 6的回答(IView已被删除)并使用方便的内置辅助方法来调用Dispose an View和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());
    }
}