2

我有一个包含 AvalonDock 的 prism/wpf/mef 解决方案。我创建了一个RegionAdapterBase<Pane>类来处理从 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));
    }

知道我错过了什么吗?

4

3 回答 3

2

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

else if (e.Action == NotifyCollectionChangedAction.Remove) {
    foreach (DockableContent content in regionTarget.Items)
        content.Content = null;
    regionTarget.Items.Clear();
}
于 2011-02-14T15:25:40.963 回答
2

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

但是,这很有效,当我尝试重新打开选项卡时,它显示的是相同的实例。看完这篇In Composite WPF (Prism),IRegion.Add 和 IRegionManager.RegisterViewWithRegion 有什么区别? 我改变了这个:

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

对此:

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

我仍然需要对 Prism / avalondock 进行一些研究,以确保不会出现内存泄漏,但到目前为止它似乎正在工作。

于 2011-02-14T15:57:01.470 回答
1

您可能还需要将其删除regionTarget

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

于 2011-02-14T15:10:15.477 回答