Prism RegionAdapter - 删除然后添加视图

发布于 2024-10-17 08:00:18 字数 2538 浏览 5 评论 0原文

我有一个包含 AvalonDock 的 prism/wpf/mef 解决方案。我创建了一个 RegionAdapterBase 类,用于处理从 AvalonDock 中创建和删除窗格。

这是我遇到的问题:

  1. 我单击菜单中的一个按钮,视图注册到一个区域并显示在我的 DocumentPane
  2. 我单击 AvalonDock 中的关闭按钮来关闭选项卡并删除查看
  3. 我单击相同的菜单按钮再次将其添加回来
  4. 我收到错误:

“指定的元素已经是 另一个元素的逻辑子元素。 先断开连接。”

所以...这告诉我有一些东西需要删除,但我无法弄清楚它在哪里。这是我的 RegionAdapter 中的一些代码:

private void OnViewsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e, IRegion region, Pane regionTarget)
{
    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        foreach (object item in e.NewItems)
        {
            UIElement view = item as UIElement;

            if (view is ITabViewInfo)
            {
                if (view != null)
                {
                    DockableContent newContentPane = new DockableContent()
                    {
                        Content = item,
                        Title = ((ITabViewInfo)view).TabViewTitle,
                        Icon = new Image()
                        {
                            Source = new BitmapImage(((ITabViewInfo)view).TabViewIcon)
                        }.Source,
                        IsCloseable = ((ITabViewInfo)view).IsCloseable,
                        HideOnClose = ((ITabViewInfo)view).IsHideOnClose
                    };

                    newContentPane.Closed += (contentPaneSender, args) =>
                    {
                        Debug.WriteLine("Removing view from region", "Prism");
                        region.Remove(item);
                    };

                    regionTarget.Items.Add(newContentPane);
                    newContentPane.Activate();
                }
            }
        }
    } else if (e.Action == NotifyCollectionChangedAction.Remove) {
            regionTarget.Items.Clear();
    }
   }

从我的调试行中,DocumentPane 和区域视图被正确地销毁...当我单击将项目添加回视图时,我在执行以下操作的行上收到上述错误消息:

Content = item,

这是按下菜单按钮时运行的模块中的代码:

    if (_regionManager.Regions["MainRegion"].Views.Any(m => m.GetType() == typeof(Views.ClassicFrontierView)))
    {
        Debug.WriteLine(_regionManager.Regions["MainRegion"].Views.Count());
    }
    else
    {
        Debug.WriteLine("Adding view to region", "Prism");
        _regionManager.RegisterViewWithRegion("MainRegion", typeof(Views.ClassicFrontierView));
    }

知道我错过了什么吗?

I have a prism/wpf/mef solution that contains an AvalonDock. I created a RegionAdapterBase<Pane> class that handles creating and removing the Panes from AvalonDock.

Heres the problem I'm running into:

  1. I click a button in my menu and a view is registered with a region and displayed in my DocumentPane
  2. I click the close button in AvalonDock to close the tab and remove the view
  3. I click the same menu button to add it back again
  4. I receive the error:

"Specified element is already the
logical child of another element.
Disconnect it first."

So... this tells me that something is lingering that I need to remove, but I cannot figure out where it is. Heres some code from my RegionAdapter:

private void OnViewsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e, IRegion region, Pane regionTarget)
{
    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        foreach (object item in e.NewItems)
        {
            UIElement view = item as UIElement;

            if (view is ITabViewInfo)
            {
                if (view != null)
                {
                    DockableContent newContentPane = new DockableContent()
                    {
                        Content = item,
                        Title = ((ITabViewInfo)view).TabViewTitle,
                        Icon = new Image()
                        {
                            Source = new BitmapImage(((ITabViewInfo)view).TabViewIcon)
                        }.Source,
                        IsCloseable = ((ITabViewInfo)view).IsCloseable,
                        HideOnClose = ((ITabViewInfo)view).IsHideOnClose
                    };

                    newContentPane.Closed += (contentPaneSender, args) =>
                    {
                        Debug.WriteLine("Removing view from region", "Prism");
                        region.Remove(item);
                    };

                    regionTarget.Items.Add(newContentPane);
                    newContentPane.Activate();
                }
            }
        }
    } else if (e.Action == NotifyCollectionChangedAction.Remove) {
            regionTarget.Items.Clear();
    }
   }

From my debug lines, the DocumentPane and region views are properly being destroyed... when I click to add the item back to the view, I get the above error message on the line that does:

Content = item,

Heres the code from my module that runs when the menu button is pressed:

    if (_regionManager.Regions["MainRegion"].Views.Any(m => m.GetType() == typeof(Views.ClassicFrontierView)))
    {
        Debug.WriteLine(_regionManager.Regions["MainRegion"].Views.Count());
    }
    else
    {
        Debug.WriteLine("Adding view to region", "Prism");
        _regionManager.RegisterViewWithRegion("MainRegion", typeof(Views.ClassicFrontierView));
    }

Any idea what I'm missing?

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

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

发布评论

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

评论(3

偏爱你一生 2024-10-24 08:00:18

您是否每次都创建一个新视图,或者多次尝试显示现有视图?如果第二个是正确的我会尝试这个:

else if (e.Action == NotifyCollectionChangedAction.Remove) {
    foreach (DockableContent content in regionTarget.Items)
        content.Content = null;
    regionTarget.Items.Clear();
}

Do you create a new View each time or you trying to show existing View several times? If second is correct I would try this:

else if (e.Action == NotifyCollectionChangedAction.Remove) {
    foreach (DockableContent content in regionTarget.Items)
        content.Content = null;
    regionTarget.Items.Clear();
}
孤独患者 2024-10-24 08:00:18

我没有处理 Closed 事件(可能丢失了对基础视图的引用),而是处理 Closing 事件。

然而,当我尝试重新打开选项卡时,它显示的是相同的实例。阅读此在复合WPF中(Prism),IRegion.Add 和 IRegionManager.RegisterViewWithRegion 之间有什么区别?我改变了这一点:

_regionManager.RegisterViewWithRegion("MainRegion", typeof(Views.ClassicFrontierView));

对此:

_regionManager.Regions["MainRegion"].Add(new Classic.Views.ClassicFrontierView());

我仍然需要使用 Prism / avalondock 进行一些研究以确保不会出现内存泄漏,但是截至目前,它似乎正在发挥作用。

Instead of handling the Closed event (which may have lost a reference to the underlying view), I handle the Closing event.

This worked, however, when I tried to re-open the tab, it was displaying the same instance. After reading this In Composite WPF (Prism), what is the difference between IRegion.Add and IRegionManager.RegisterViewWithRegion? I changed this:

_regionManager.RegisterViewWithRegion("MainRegion", typeof(Views.ClassicFrontierView));

to this:

_regionManager.Regions["MainRegion"].Add(new Classic.Views.ClassicFrontierView());

I still have to do some research with Prism / avalondock to make sure there will be no memory leaks, but as of now it appears to be working.

旧情勿念 2024-10-24 08:00:18

您可能还需要从 regionTarget 中删除它。

您可以使用 Snoop 查看尚未从 Visual Tree 中删除的内容,然后尝试查找您需要的容器从中删除您的元素。其他可能性包括未冻结的图标图像等。

You likely need to remove it from regionTarget as well.

You can use Snoop to see what hasn't been removed from the Visual Tree and then attempt to find which container you need to remove your element from. Other possibilities are things like an unfrozen Icon image, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文