I am doing this in Caliburn Micro:
The view that host the Content Control:
<Controls:TransitioningContentControl Grid.Row=" Grid.Column=" x:Name="ActiveItem"/>
Test code in the view model - basically a timer that will assign TestSiteCollection[0] & TestSiteCollection[1] to ActiveItem repeatedly.
private void tmrMemTest_Tick(object sender, EventArgs e){ if (isAddLimit) { ActiveItem = TestSiteCollection[1]; isAddLimit = false; } else { ActiveItem = TestSiteCollection[0]; isAddLimit = true; GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); // to see whether we have a leak or not. }}One of the TestSiteCollection elements is the RadDocking & its view look likes this.
<telerik:RadDocking Grid.Row=" HasDocumentHost=" PanesSource="{Binding TestPanelCollection, Mode=OneWay}"> <telerik:RadDocking.DockingPanesFactory>
<styles:CustomDockingPanesFactory/>
</telerik:RadDocking.DockingPanesFactory>
<telerik:RadSplitContainer InitialPosition="DockedLeft">
<telerik:RadPaneGroup x:Name="leftGroup" telerik:RadDocking.SerializationTag="leftGroup"/>
</telerik:RadSplitContainer>
<telerik:RadSplitContainer InitialPosition="DockedRight">
<telerik:RadPaneGroup x:Name="rightGroup" telerik:RadDocking.SerializationTag="rightGroup"/>
</telerik:RadSplitContainer>
<telerik:RadSplitContainer InitialPosition="DockedTop">
<telerik:RadPaneGroup x:Name="topGroup" telerik:RadDocking.SerializationTag="topGroup"/>
</telerik:RadSplitContainer>
<telerik:RadSplitContainer InitialPosition="DockedBottom">
<telerik:RadPaneGroup x:Name="bottomGroup" telerik:RadDocking.SerializationTag="bottomGroup"/>
</telerik:RadSplitContainer>
</telerik:RadDocking>
CustomDockingPanesFactory:
protected override RadPane CreatePaneForItem(object item){ var viewModel = item as TestPanelBase; if (viewModel != null) { var pane = viewModel.IsDocument ? new RadDocumentPane() : new RadPane(); pane.DataContext = item; pane.Header = viewModel.Header; // When saving the layout, RadDocking control generates an xml schema for its elements and their position, // size and other properties. // We need to set a SerializationTag for each Pane. Otherwise, each time when loading, // a new Pane will be generated and we will lose the DataContext, which is not desirable. RadDocking.SetSerializationTag(pane, viewModel.Header); if (viewModel.ContentType != null) { pane.Content = Activator.CreateInstance(viewModel.ContentType); } return pane; } return base.CreatePaneForItem(item);}protected override void RemovePane(RadPane pane){ // A problem could exist if you hold a reference to the old content or it was declared in XAML. // There is one memory leak in the Docking control we are aware of - // if you are removing the whole pane and it was the last one in the group, // it is not destroyed before you add another pane in this group pane.ClearValue(RadDocking.SerializationTagProperty); // Removes the Pane from the RadDocking layout. By default clears the Header, Content, DataContext and call RemoveFromParent method. base.RemovePane(pane);}
What i have observed is that every time ActiveItem is assigned, CreatePaneForItem() is called. I am suspecting that is the cause of the memory leak.
What can i do to prevent this multiple call to CreatePaneForItem()?
p/s: i have cleaned up other misbehaving codes that have contributed to the memory leak & i am now stuck at this observation.