Prism RegionAdapter - Removing then Adding View

依然范特西╮ 提交于 2019-12-12 20:57:20

问题


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?


回答1:


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();
}



回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/4993705/prism-regionadapter-removing-then-adding-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!