Reputation: 9973
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:
DocumentPane
"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?
Upvotes: 2
Views: 4933
Reputation: 9973
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.
Upvotes: 2
Reputation: 64068
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.
Upvotes: 1
Reputation: 17274
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();
}
Upvotes: 2