This is a migrated thread and some comments may be shown as answers.

Loading Pane Content results in InvalidOperationException

3 Answers 94 Views
Docking
This is a migrated thread and some comments may be shown as answers.
Kareema
Top achievements
Rank 2
Kareema asked on 26 Jul 2012, 09:43 AM
Hello

Please refer to the telerik "Save/Load the Content of the Panes" docking topic. I'm trying to load the layout of my docking control in this way when navigating away and then returning to this screen to maintain view state. This page refers to the following piece of code:
private void radDocking_ElementLoading( object sender, Telerik.Windows.Controls.LayoutSerializationLoadingEventArgs e )
{
    var pane = e.AffectedElement as RadPane;
    if ( pane != null )
    {
        pane.Content = this.GetPaneContent( e.AffectedElementSerializationTag );
    }
}

I assume that "GetPaneContent" refers to some internal method in the code-behind which returns the content, whatever that control may have been before the content was saved. Since I am using MVVM and adding RadPanes and RadPaneGroups dynamically in my view model, I maintain a dictionary of the pane contents by the serialization tag that I assign to each one. This view model code is as follows:

RadPaneGroup radPaneGroup = new RadPaneGroup { VerticalAlignment = VerticalAlignment.Top, VerticalContentAlignment = VerticalAlignment.Top };
            this.view.splitContainer.Items.Add(radPaneGroup);
            RadPane radPane = new RadPane
                                          {
                                              Content = createdChartView,
                                              CanUserClose = true,
                                              Title = createdChartView.DisplayName,
                                          };
            RadDocking.SetSerializationTag(radPane, chartConfiguration.Id.ToString());
            RadDocking.SetSerializationTag(radPaneGroup, chartConfiguration.Id.ToString());
 
            radPaneGroup.Items.Add(radPane);
            this.hostedCharts.Add(chartConfiguration.Id, createdChartView);

To explain, chartConfiguration.Id is a Guid which serves as a string tag and hostedCharts is a field of type Dictionary<Guid, ChartView>.
I use this dictionary to get the ChartView when I reload the layout. ChartView is the content I want to reset as the content of the pane.

My element loading event handler looks like this:

private void RadDockingOnElementLoaded(object sender, LayoutSerializationEventArgs e)
        {
            RadPane newPane = e.AffectedElement as RadPane;
            if (newPane != null)
            {
                ChartView chartView = ((ChartHostViewModel)this.DataContext).GetPaneContent(e.AffectedElementSerializationTag);
 
// This entire section is to try to remove the chart from its parent all the way up the visual tree.
                RadPane oldParentPane = (RadPane)chartView.Parent;
                if (oldParentPane != null)
                {
                    RadPaneGroup oldParentGroup = (RadPaneGroup)oldParentPane.Parent;
                    if (oldParentGroup != null)
                    {
                        RadSplitContainer oldSplitContainer = (RadSplitContainer)oldParentGroup.Parent;
 
                        if (oldSplitContainer != null)
                        {
                            oldSplitContainer.Items.Remove(oldParentGroup);
 
                        }
                        oldParentGroup.Items.Remove(oldParentPane);
                    }
                    oldParentPane.Content = null;
                }
 
                newPane.Content = chartView;
                return;
            }
 
// This section is here because the pane groups fill up the entire space if I leave it out (They seem to be aligned to Stretch)
            RadPaneGroup newPaneGroup = e.AffectedElement as RadPaneGroup;
            if (newPaneGroup != null)
            {
                newPaneGroup.VerticalAlignment = VerticalAlignment.Top;
                newPaneGroup.VerticalContentAlignment = VerticalAlignment.Top;
            }
        }

Here's my concern:
Firstly, if I remove the code to try to remove the ChartView from its parent, I get an InvalidOperationException saying to first disconnect the element before adding it to a new one on the line, "newPane.Content = chartView;" . It seems that the entire visual tree is still intact and reloading the screen creates new visual elements and adds these to the Docking component. Is this not memory intensive? Please note that this screen's (my screen, "ChartHostView")'s lifestyle is Transient and may be affecting the way it should work.

Secondly, my pane groups are not being loaded in the state that I saved them in. Why is it necessary for me re-set their Vertical Alignment ?

Please let me know if I am going about this the completely wrong way.
Thank you.

3 Answers, 1 is accepted

Sort by
0
Kareema
Top achievements
Rank 2
answered on 26 Jul 2012, 09:58 AM
Forgot to mention the third concern:

If after I have reloaded the docking layout, I try to rerun the second code extract (ie, add more panes to the docking) I don't see the panes being added. Is this because the groups are being added to a different (old) split container that got removed from the document host or what?
0
Kareema
Top achievements
Rank 2
answered on 26 Jul 2012, 10:28 AM
0
Accepted
Miroslav Nedyalkov
Telerik team
answered on 30 Jul 2012, 07:48 AM
Hello,

Here is the answer we provided in the support thread:

The GetPaneContent method is not something internal, but a method you should create in your code to find the correct content for the corresponding pane. By default we are using the contents which panes currently contain when the Load method is called using the SerializationTag to match the panes so in most cases you don't need to implement any custom logic to save and load the content except in the cases when panes are dynamically added to the docking control. In these cases you need to hook to the event and implement your custom logic for loading/finding the correct content for the pane.

What the docking control does when you call the LoadLayout method is to detach all the docking components (Panes, Groups and SplitContainers) from one another and to store the ones that have SerializationTag set in a Dictionary by SerializationTag. After that it starts loading the Layout from the XML provided and when it finds an item with SerializationTag set it tries to find it in the dictionary and it succeeds it reuses the component. Please notice that in your case the chart is not removed from the Pane as the Docking control intends to reuse the Pane so if you are not reusing the pane you should clear its content manually (with your RemoveFromParent method).

The reason why the pane is not visible when the AddPane method is called because all docking components which doesn't have SerializationTag set are removed from the Docking control and are not used anymore. My advise is to set SerializationTag to all Docking elements which have x:Name set. 

Kind regards,
Miroslav Nedyalkov
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

Tags
Docking
Asked by
Kareema
Top achievements
Rank 2
Answers by
Kareema
Top achievements
Rank 2
Miroslav Nedyalkov
Telerik team
Share this question
or