如何在PRISM中每次导航发生时创建一个新视图?

6
我正在使用WPF4和PRISM4开发我的新项目。
这个项目只有一个模块,里面包含了几个视图。依赖注入是通过Unity实现的。当我第一次从ViewA导航到ViewB时,ViewB会被创建并调用其构造函数。但是当我尝试第二、第三次导航到ViewB时,ViewB不会被重新创建,而是重用现有的实例。
我使用IRegionManager.RequestNavigate进行导航。
我已经尝试将TransientLifeTimeManager传递给RegisterType Unity方法,但没有成功。
有没有办法配置prism和/或unity,在每次导航到视图时都创建一个新的视图?
谢谢。
3个回答

20
正确的做法是在你的 View 或 ViewModel 中实现 INavigationAware 接口(Prism 先检查视图,如果它没有实现 INavigationAware 接口,则还会检查 ViewModel)。
你特别关注的是 IsNavigationTarget 方法,它告诉 Prism 是否应该重用当前 View 的实例,或者是否应该创建另一个实例以满足导航请求。所以,要始终创建新的 View,您可以这样做:
public class MyViewModel : INavigationAware {
    bool INavigationAware.IsNavigationTarget(NavigationContext navigationContext)
    {
        return false;
    }

    void INavigationAware.OnNavigatedFrom(NavigationContext navigationContext)
    {
    }

    void INavigationAware.OnNavigatedTo(NavigationContext navigationContext)
    {
    }
}

所有这些都在Prism 4文档的第8章中有更详细的解释;他们还有一个演示它如何工作的例子,这非常棒,因为它还可以让您准确地了解您可以在哪里挂钩以及如何挂钩。


2
一个小补充,如果使用MEF进行依赖注入,您应该确保您的视图具有属性[PartCreationPolicy(CreationPolicy.NonShared)]。否则,ServiceLocator将返回相同的实例,而不管IsNavigateTarget逻辑如何。导航服务会看到该区域已经包含该实例并激活它。我曾经困惑了很长时间。 - Gusdor
这实际上解决了我的相反问题。我的条件不正确,因此一直返回false。 - Jesse Seger

18

实现IRegionMemberLifetime接口在你的视图或视图模型上,然后在KeepAlive属性中返回false即可:

public class EmployeeDetailsViewModel : IRegionMemberLifetime
{
    public bool KeepAlive
    {
        get { return false; }
    }
}

4
这并不完全正确,因为它有一个副作用,如果用户通过UI切换活动视图,那么您的EmployeeDetailsView将被从区域中移除,而不是简单地被停用。 - Jon
1
我确实假设他想在导航离开视图时将其移除,如果我错了,那么他会纠正我。我们对他的请求有不同的解释 - 我真的不明白这会让你为什么要投-1票,好像我的答案是不正确的。 - Elad Katz

1

它在区域的ActiveViews属性中内部查找视图。如果在其中不存在,则创建一个新视图并将其添加到ActiveViews以供将来使用。

要实现您想要的功能,您需要在导航到任何视图之前删除或清除ActiveView集合。

示例:

public static class RegionManagerExtensions
{
    public static void RequestNavigateEx(this IRegionManager regionManager, String regionName, Uri source)
    {
        if (regionManager != null)
        {
            IRegion region = regionManager.Regions[regionName];

            if (region != null)
            {
                foreach (Object view in region.ActiveViews)
                {
                    region.Remove(view);
                }

                regionManager.RequestNavigate(regionName, source);
            }
        }
    }
}

嘿,我尝试做这个,但最终只得到了一个空白视图。我是不是漏掉了什么? - Tri Q Tran
视图不必存在于Active View属性中;如果视图存在于Views属性中,则也不会重新创建视图。 - Mr. Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接