Edit this page

Save/Load Layout Events

With R2 2016 of UI for WPF, you can now change the default save/load layout mechanism of RadDocking. This is now possible using the ElementLayoutSaving (also available with R2 2016), ElementLoading and CustomElementLoading events of the RadDocking control.

Using the ElementLayoutSaving and ElementLoading events, you could decide which exact properties of the Pane, PaneGroup, SplitContainer or the Docking control to be saved or loaded. While using the CustomElementLoading event, you are now able to easily load custom docking elements that derive from RadPane, RadPaneGroup or RadSplitContainer. Inside the ElementLayoutSaving you could also easily exclude a specific RadPane, RadPaneGroup or RadSplitContainer from saving.

In this article, we will go through all these events:

For the current article, we will use the declaration of RadDocking shown in Example 1.

[XAML] Example 1: RadDocking declaration

<telerik:RadDocking x:Name="radDocking" 
ElementLayoutSaving="radDocking_ElementLayoutSaving"
                CustomElementLoading="radDocking_CustomElementLoading"
                ElementLayoutCleaning="radDocking_ElementLayoutCleaning">
    <telerik:RadDocking.DocumentHost>
        <telerik:RadSplitContainer>
            <telerik:RadPaneGroup x:Name="DocumentGroup">
                <telerik:RadDocumentPane Header="Document 1" Title="Document 1" telerik:RadDocking.SerializationTag="DocumentPane">
                    <TextBox x:Name="DocumentTextBox" Text="Some text" />
                </telerik:RadDocumentPane>
            </telerik:RadPaneGroup>
        </telerik:RadSplitContainer>
    </telerik:RadDocking.DocumentHost>
    <telerik:RadSplitContainer InitialPosition="DockedLeft">
        <telerik:RadPaneGroup telerik:RadDocking.SerializationTag="PaneGroup">
            <telerik:RadPane Header="Pane Left 1"  telerik:RadDocking.SerializationTag="PaneLeft1">
                <TextBox x:Name="TextBox" Text="Some other text" />
            </telerik:RadPane>
            <telerik:RadPane Header="Pane Left 2"  telerik:RadDocking.SerializationTag="PaneLeft2">
                <TextBox Text="Pane Left 2" />
            </telerik:RadPane>
            <telerik:RadPane Header="Pane Left 3"  telerik:RadDocking.SerializationTag="PaneLeft3">
                <TextBox Text="Pane Left 3" />
            </telerik:RadPane>
            <telerik:RadPane Header="Pane Left 4"  telerik:RadDocking.SerializationTag="PaneLeft4">
                <TextBox Text="Pane Left 4" />
            </telerik:RadPane>
        </telerik:RadPaneGroup>
    </telerik:RadSplitContainer>
    <telerik:RadSplitContainer InitialPosition="DockedTop">
        <telerik:RadPaneGroup>
            <telerik:RadPane Header="Pane Top 1" telerik:RadDocking.SerializationTag="PaneTop1">
                <TextBox Text="Pane Top 1" />
            </telerik:RadPane>
        </telerik:RadPaneGroup>
    </telerik:RadSplitContainer>
</telerik:RadDocking>

If you run the application now, you will see a docking with some SplitContainers, PaneGroups and Panes, as shown in Figure 1.

Figure 1: RadDocking generated by the code in Example 1

Saving Properties

By handling the ElementLayoutSaving event of RadDocking, you could save any desired property of the element (Pane, PaneGroup, SplitContainer or the Docking control) that is currently saving or exclude that element from saving. This is possible using the ElementProperties dictionary and the Cancel property of the LayoutSerializationSavingEventArgs of the event.

The event is only called for the elements that have a set SerializationTag. However, you have the ability to "say" whether this event should be fired or not, when the SerializationTag is not specified. You should set the second overload of the LoadLayout and SaveLayout methods to True.

The ElementProperties property is of type Dictionary. The value and its associated key should be of type string - the key is the name of the property you want to save.
Example 2 demonstrates how you could easily add the CanFloat property of a Pane to the dictionary you want to save in the XML.

[C#] Example 2: Adding properties to ElementProperties

private void radDocking_ElementLayoutSaving(object sender, LayoutSerializationSavingEventArgs e)
{
    var pane = e.AffectedElement as RadPane;

    if (e.AffectedElementSerializationTag.Equals("PaneTop1") && pane != null)
    {
        e.ElementProperties.Add("CanFloat", pane.CanFloat.ToString());
    }
}

If you want to prevent some of the already saved properties included in the dictionary from being saved again, you could just remove them from it.

Example 3 demonstrates how you could exclude the Header of a pane from saving.

[C#] Example 3: Prevent properties from saving

private void radDocking_ElementLayoutSaving(object sender, LayoutSerializationSavingEventArgs e)
{
    var pane = e.AffectedElement as RadPane;

    if (e.AffectedElementSerializationTag.Equals("PaneTop1") && pane != null)
    {
        e.ElementProperties.Add("CanFloat", pane.CanFloat.ToString());
        if (e.ElementProperties.ContainsKey("Header"))
        {
            e.ElementProperties.Remove("Header");
        }
    }
}

Example 4 shows the generated XML after the execution of the code of Example 3 - notice the Header of the "PaneTop1" was not saved, but the CanFloat property was.

[XAML] Example 4: Generated XML after saving

<RadDocking SerializationTag="dock">
    <DocumentHost>
        <RadSplitContainer>
            <Items>
                <RadPaneGroup SelectedIndex="0">
                    <Items>
                        <RadDocumentPane SerializationTag="DocumentPane" IsDockable="True" Title="Document 1" Header="Document 1" />
                    </Items>
                </RadPaneGroup>
            </Items>
        </RadSplitContainer>
    </DocumentHost>
    <SplitContainers>
        <RadSplitContainer Dock="DockedLeft" Width="240">
            <Items>
                <RadPaneGroup SerializationTag="PaneGroupLeft" SelectedIndex="0">
                    <Items>
                        <RadPane SerializationTag="PaneLeft1" IsDockable="True" Header="Pane Left 1" />
                        <RadPane SerializationTag="PaneLeft2" IsDockable="True" Header="Pane Left 2" />
                        <RadPane SerializationTag="PaneLeft3" IsDockable="True" Header="Pane Left 3" />
                        <RadPane SerializationTag="PaneLeft4" IsDockable="True" Header="Pane Left 4" />
                    </Items>
                </RadPaneGroup>
            </Items>
        </RadSplitContainer>
        <RadSplitContainer Dock="DockedTop" Height="180">
            <Items>
                <RadPaneGroup SelectedIndex="0">
                    <Items>
                        <RadPane SerializationTag="PaneTop1" IsDockable="True" CanFloat="False" />
                    </Items>
                </RadPaneGroup>
            </Items>
        </RadSplitContainer>
    </SplitContainers>
</RadDocking>

Using the Cancel property of the LayoutSerializationSavingEventArgs, you could easily exclude a specific RadPane, RadSplitContainer or RadPaneGroup from saving. In order to do so, the Cancel property should be set to True.

Example 5 demonstrates how to exclude a specific RadPane and RadPaneGroup from saving.

[C#] Example 5: Exclude from saving

private void radDocking_ElementLayoutSaving(object sender, LayoutSerializationSavingEventArgs e)
{
    if (e.AffectedElementSerializationTag.Equals("PaneGroup") ||
        e.AffectedElementSerializationTag.Equals("DocumentPane"))
    {
        e.Cancel = true;
    }
}

The generated XML file after executing the code in Example 5 is shown in Example 6.

[XAML] Example 6: Generated XML after saving

<RadDocking SerializationTag="dock">
    <DocumentHost>
        <RadSplitContainer>
            <Items>
                <RadPaneGroup SelectedIndex="0">
                    <Items />
                </RadPaneGroup>
            </Items>
        </RadSplitContainer>
    </DocumentHost>
    <SplitContainers>
        <RadSplitContainer Dock="DockedLeft" Width="240">
            <Items />
        </RadSplitContainer>
        <RadSplitContainer Dock="DockedTop" Height="180">
            <Items>
                <RadPaneGroup SelectedIndex="0">
                    <Items>
                        <RadPane SerializationTag="PaneTop1" IsDockable="True" Header="Pane Top 1" />
                    </Items>
                </RadPaneGroup>
            </Items>
        </RadSplitContainer>
    </SplitContainers>
</RadDocking>

Figure 2 visualizes how RadDocking looks after loading the saved layout.

Figure 2: RadDocking after execution of Example 5

Loading Properties

In order to prevent a specific property from loading, the ElementLoading event needs to be handled. By using the ElementProperties dictionary (that contains all saved properties) you could simply remove the properties that should not be loaded.

The event is only called for the elements that have a set SerializationTag. However, you have the ability to "say" whether this event should be fired or not, when the SerializationTag is not specified. You should set the second overload of the LoadLayout and SaveLayout methods to True.

Example 7 demonstrates how to prevent the Header property of the left docked Panes from loading.

[C#] Example 7: Loading properties

private void radDocking_CustomElementLoading(object sender, LayoutSerializationCustomLoadingEventArgs e)
{
    if (e.CustomElementTypeName == "MyRadPane")
    {
        e.SetAffectedElement(new MyRadPane());
    }
}

In Figure 3 you can see how the left docked PaneGroup visualizes after the layout is loaded.

Figure 3: RadDocking after execution of Example 7

Loading Custom Elements

In order to load a custom element other than the built-in RadSplitContainer, RadPaneGroup and RadPane instances, the CustomElementLoading event needs to be handled. The event will be called when loading the layout and if there is an unknown type of element. All that needs to be done in order for the layout to be loaded as expected is to set the AffectedElement with the correct object.

The event will be called only for the Panes, PaneGroups and SplitContainers that do not have a set SerializationTag. Otherwise, the ElementLoading will be called.

Example 7 demonstrates how to load a custom pane (for example, "MyRadPane") that derives from the default RadPane class.

[C#] Example 6: Custom loading of elements

private void radDocking_CustomElementLoading(object sender, LayoutSerializationCustomLoadingEventArgs e)
{
    if (e.CustomElementTypeName == "MyRadPane")
    {
        e.SetAffectedElement(new MyRadPane());
    }
}

ElementLayoutCleaning

When the saved layout of RadDocking starts loading, the current layout of RadDocking (all RadPanes, RadPaneGroups and RadSplitContainers) is cleaned. In order to prevent an element from being cleaned, the ElementLayoutCleaning (introduced with R2 2016 of UI for WPF) event could be handled. Inside it, by using the Cancel property of the LayoutSerializationCleaningEventArgs, a specific element of RadDocking could be prevented from being cleaned.

The event does not get called for the RadDocking control, but only for its elements - RadPane, RadPaneGroup and RadSplitContainer.

Example 8 demonstrates how to prevent a PaneGroup from being cleaned when the layout is about to be loaded.

[C#] Example 8: Prevent element from cleaning

private void radDocking_ElementLayoutCleaning(object sender, LayoutSerializationCleaningEventArgs e)
{
    if (e.AffectedElementSerializationTag.Contains("PaneLeft"))
    {
        e.Cancel = true;
    }
}

See Also