wpfprismregionsavalondockregionadapter

Prism RegionAdapter - Removing then Adding View


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?


Solution

  • 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.