视图导航棱镜

发布于 2024-11-05 09:14:13 字数 198 浏览 1 评论 0原文

嘿伙计们,
我正在使用 Prism 4 来实现我的演示, 问题是我正在使用包含区域的视图,现在我想导航到同一范围下的视图的其他实例,因此我将视图的 KeepAlive 属性设置为 false,以便在导航中视图将从区域和新视图将会出现,但我不断收到区域名称已存在的异常。
如何在包含区域的同一视图的几个实例之间导航(当时内存中应该只有一个)
谢谢
埃兰

Hey guys,
I'm using prism 4 to implement my presentation,
the thing is that i'm using view that contains region,now I want to navigate to other instance of the view under the same scope so I set the KeepAlive property of the view to false so that in navigation the view will be removed from the region and the new view will appear ,but I'm keep getting region name already exist exception.
how can I navigate between few instances of the same view that contain region (only one should be in memory at the time)
Thanks
Eran

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

残疾 2024-11-12 09:14:13

听起来您想将作用域 RegionManager 与导航一起使用。您看到区域名称已存在异常的原因是因为同一 RegionManager 中有多个具有相同名称的区域。

默认情况下,PRISM 不支持带导航的作用域 RegionManager,但如果您使用自定义 RegionBehaviors,则添加此功能非常容易。本质上,您需要做的是创建一个接口,然后在视图或视图模型上实现该接口。然后,创建一个 RegionBehavior 来查找该接口,如果满足要求,则为该视图创建一个新的 RegionManager 实例。

界面可能如下所示:

public interface IRegionScopeAware
{
    bool IsRegionManagerScoped { get; }
}

RegionBehavior 可能如下所示:

public class RegionScopeAwareBehavior : RegionBehavior
{
    #region Overrides of RegionBehavior

    protected override void OnAttach()
    {
        Region.Views.CollectionChanged += ViewsOnCollectionChanged;
        ApplyScopedRegionManager(Region.Views.OfType<FrameworkElement>());
    }

    #endregion

    private static void ViewsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems == null || e.Action != NotifyCollectionChangedAction.Add) return;
        ApplyScopedRegionManager(e.NewItems.OfType<DependencyObject>());
    }

    private static void ApplyScopedRegionManager(IEnumerable<DependencyObject> views)
    {
        if (views == null) return;
        foreach (var view in views)
        {
            ApplyScopedRegionManager(view);
        }
    }

    private static void ApplyScopedRegionManager(DependencyObject view)
    {
        if (view == null) return;
        IRegionScopeAware scopeAware = view as IRegionScopeAware;
        if (scopeAware == null && view is FrameworkElement)
            scopeAware = ((FrameworkElement) view).DataContext as IRegionScopeAware;
        if (scopeAware != null)
            ApplyScopedRegionManager(scopeAware, view);
    }

    private static void ApplyScopedRegionManager(IRegionScopeAware scopeAware, DependencyObject view)
    {
        if (view == null) return;
        if (scopeAware == null) return;
        if (scopeAware.IsRegionManagerScoped)
            RegionManager.SetRegionManager(view, new RegionManager());
    }
}

不要忘记您需要注册 RegionBehavior。我建议将其注册为引导程序中的默认 RegionBehavior,如下所示:

        protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()
        {
            IRegionBehaviorFactory factory = base.ConfigureDefaultRegionBehaviors();
            factory.AddIfMissing(typeof(RegionScopeAwareBehavior).Name, typeof(RegionScopeAwareBehavior));
            return factory;
        }

It sounds like you want to use a scoped RegionManager with navigation. The reason you're seeing the region name already exists exception is because you have more than one region with the same name in the same RegionManager.

By default, PRISM doesn't support scoped RegionManagers with navigation, but it's pretty easy to add this in if you use custom RegionBehaviors. Essentially what you need to do is create an interface and then implement that interface on your view or view model. Then, create a RegionBehavior that looks for that interface and, if it meets the requirements, creates a new RegionManager instance for that view.

Here's what the interface might look like:

public interface IRegionScopeAware
{
    bool IsRegionManagerScoped { get; }
}

And here's what the RegionBehavior might look like:

public class RegionScopeAwareBehavior : RegionBehavior
{
    #region Overrides of RegionBehavior

    protected override void OnAttach()
    {
        Region.Views.CollectionChanged += ViewsOnCollectionChanged;
        ApplyScopedRegionManager(Region.Views.OfType<FrameworkElement>());
    }

    #endregion

    private static void ViewsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems == null || e.Action != NotifyCollectionChangedAction.Add) return;
        ApplyScopedRegionManager(e.NewItems.OfType<DependencyObject>());
    }

    private static void ApplyScopedRegionManager(IEnumerable<DependencyObject> views)
    {
        if (views == null) return;
        foreach (var view in views)
        {
            ApplyScopedRegionManager(view);
        }
    }

    private static void ApplyScopedRegionManager(DependencyObject view)
    {
        if (view == null) return;
        IRegionScopeAware scopeAware = view as IRegionScopeAware;
        if (scopeAware == null && view is FrameworkElement)
            scopeAware = ((FrameworkElement) view).DataContext as IRegionScopeAware;
        if (scopeAware != null)
            ApplyScopedRegionManager(scopeAware, view);
    }

    private static void ApplyScopedRegionManager(IRegionScopeAware scopeAware, DependencyObject view)
    {
        if (view == null) return;
        if (scopeAware == null) return;
        if (scopeAware.IsRegionManagerScoped)
            RegionManager.SetRegionManager(view, new RegionManager());
    }
}

And don't forget that you'll need to register your RegionBehavior. I suggest registering it as a default RegionBehavior in the bootstrapper like so:

        protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()
        {
            IRegionBehaviorFactory factory = base.ConfigureDefaultRegionBehaviors();
            factory.AddIfMissing(typeof(RegionScopeAwareBehavior).Name, typeof(RegionScopeAwareBehavior));
            return factory;
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文