Quite often the users might want to save and then restore the layout they have previously left when closing an application that uses any kind of docking layout management. The powerful Save/Load layout mechanism of Telerik RadDocking enables such users to accomplish this task in an absolutely straight-forward manner. The developers building the application can use the advanced API of the control and implement the needed logic with just a few lines of code.
The example below demonstrates how to persist the panes’ position in a Weather Forecast Browser built specifically for this blog post.
This is the first of series of blog posts dedicated on creating a Weather Forecast Browser application that will support Save/Load layout.
1: <UserControl x:Class="WeatherStation.Page"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:telerikNavigation="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation"
5: xmlns:telerikDocking="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Docking">
6: <Grid x:Name="LayoutRoot" Background="White">
7: <Grid.RowDefinitions>
8: <RowDefinition Height="Auto" />
9: <RowDefinition Height="*" />
10: </Grid.RowDefinitions>
11: <TextBlock Grid.Row="0" Text="The menu comes here" />
12: <telerikDocking:RadDocking Grid.Row="1">
13: </telerikDocking:RadDocking>
14: </Grid>
15: </UserControl>
1: <telerikDocking:RadSplitContainer InitialPosition="DockedLeft">
2: <telerikDocking:RadPaneGroup>
3: <telerikDocking:RadPane Header="Cities">
4: <TextBlock Text="Cities view comes here" />
5: </telerikDocking:RadPane>
6: </telerikDocking:RadPaneGroup>
7: </telerikDocking:RadSplitContainer>
1: <telerikDocking:RadSplitContainer InitialPosition="DockedRight" Orientation="Vertical">
2: <telerikDocking:RadPaneGroup>
3: <telerikDocking:RadPane Header="Morning">
4: <TextBlock Text="Morning view comes here" />
5: </telerikDocking:RadPane>
6: </telerikDocking:RadPaneGroup>
7:
8: <telerikDocking:RadPaneGroup>
9: <telerikDocking:RadPane Header="Noon">
10: <TextBlock Text="Noon view comes here" />
11: </telerikDocking:RadPane>
12: </telerikDocking:RadPaneGroup>
13:
14: <telerikDocking:RadPaneGroup>
15: <telerikDocking:RadPane Header="Evening">
16: <TextBlock Text="Evening view comes here" />
17: </telerikDocking:RadPane>
18: </telerikDocking:RadPaneGroup>
19: </telerikDocking:RadSplitContainer>
1: <telerikDocking:RadDocking.DocumentHost>
2: <telerikDocking:RadSplitContainer>
3: <telerikDocking:RadPaneGroup>
4: <telerikDocking:RadPane Header="Main view">
5: <TextBlock Text="The main view comes here" />
6: </telerikDocking:RadPane>
7: </telerikDocking:RadPaneGroup>
8: </telerikDocking:RadSplitContainer>
9: </telerikDocking:RadDocking.DocumentHost>
1: <telerikDocking:RadDocking Grid.Row="1">
2: <telerikDocking:RadSplitContainer InitialPosition="DockedLeft">
3: <telerikDocking:RadPaneGroup>
4: <telerikDocking:RadPane Header="Cities"
5: telerikDocking:RadDocking.SerializationTag="CitiesPane">
6: <TextBlock Text="Cities view comes here" />
7: </telerikDocking:RadPane>
8: </telerikDocking:RadPaneGroup>
9: </telerikDocking:RadSplitContainer>
10:
11: <telerikDocking:RadSplitContainer InitialPosition="DockedRight" Orientation="Vertical">
12: <telerikDocking:RadPaneGroup>
13: <telerikDocking:RadPane Header="Morning"
14: telerikDocking:RadDocking.SerializationTag="MorningPane">
15: <TextBlock Text="Morning view comes here" />
16: </telerikDocking:RadPane>
17: </telerikDocking:RadPaneGroup>
18:
19: <telerikDocking:RadPaneGroup>
20: <telerikDocking:RadPane Header="Noon"
21: telerikDocking:RadDocking.SerializationTag="NoonPane">
22: <TextBlock Text="Noon view comes here" />
23: </telerikDocking:RadPane>
24: </telerikDocking:RadPaneGroup>
25:
26: <telerikDocking:RadPaneGroup>
27: <telerikDocking:RadPane Header="Evening"
28: telerikDocking:RadDocking.SerializationTag="EveningPane">
29: <TextBlock Text="Evening view comes here" />
30: </telerikDocking:RadPane>
31: </telerikDocking:RadPaneGroup>
32: </telerikDocking:RadSplitContainer>
33:
34: <telerikDocking:RadDocking.DocumentHost>
35: <telerikDocking:RadSplitContainer>
36: <telerikDocking:RadPaneGroup>
37: <telerikDocking:RadPane Header="Main view"
38: telerikDocking:RadDocking.SerializationTag="MainPane">
39: <TextBlock Text="The main view comes here" />
40: </telerikDocking:RadPane>
41: </telerikDocking:RadPaneGroup>
42: </telerikDocking:RadSplitContainer>
43: </telerikDocking:RadDocking.DocumentHost>
44: </telerikDocking:RadDocking>
1: <telerikNavigation:RadMenu Grid.Row="0">
2: <telerikNavigation:RadMenuItem Header="Save layout" Click="RadMenuItemSave_Click" />
3: <telerikNavigation:RadMenuItem Header="Load layout" x:Name="LoadLayout" IsEnabled="False" Click="RadMenuItemLoad_Click" />
4: </telerikNavigation:RadMenu>
1: private byte[] layoutBytes;
2:
3: private void RadMenuItemLoad_Click(object sender, RoutedEventArgs e)
4: {
5: using (MemoryStream stream = new MemoryStream(this.layoutBytes))
6: {
7: this.docking.LoadLayout(stream);
8: }
9: }
10:
11: private void RadMenuItemSave_Click(object sender, RoutedEventArgs e)
12: {
13: using (MemoryStream stream = new MemoryStream())
14: {
15: this.docking.SaveLayout(stream);
16: this.layoutBytes = stream.GetBuffer();
17:
18: this.LoadLayout.IsEnabled = true;
19: }
20: }
1: <telerikNavigation:RadMenu Grid.Row="0">
2: <telerikNavigation:RadMenuItem Header="Save layout" Click="RadMenuItemSave_Click" />
3: <telerikNavigation:RadMenuItem Header="Load layout" x:Name="LoadLayoutMenuItem" Click="RadMenuItemLoad_Click" IsEnabled="{Binding HasSavedLayouts}" ItemsSource="{Binding SavedLayouts}" DisplayMemberPath="Key" />
4: <telerikNavigation:RadMenuItem Header="Clear saved" Click="RadMenuItemClear_Click" />
5: </telerikNavigation:RadMenu>
1: private ViewModels.WeatherStationViewModel viewModel;
2:
3: public Page()
4: {
5: InitializeComponent();
6: this.viewModel = newViewModels.WeatherStationViewModel();
7: IsolatedStoragePersister.LoadState(this.viewModel);
8: this.DataContext = this.viewModel;
9: }
1: private void RadMenuItemLoad_Click(object sender, RoutedEventArgs e)
2: {
3: var radArgs = e as RadRoutedEventArgs;
4: if (radArgs != null)
5: {
6: RadMenuItem item = radArgs.Source as RadMenuItem;
7: if (item != null && item.DataContext is KeyValuePair<string, byte[]>)
8: {
9: using (MemoryStream stream = new MemoryStream(((KeyValuePair<string, byte[]>)item.DataContext).Value))
10: {
11: this.docking.LoadLayout(stream);
12: }
13: }
14: }
15: }
16:
17: private void RadMenuItemSave_Click(object sender, RoutedEventArgs e)
18: {
19: using (MemoryStream stream = new MemoryStream())
20: {
21: this.docking.SaveLayout(stream);
22: byte[] layoutBytes = stream.GetBuffer();
23:
24: this.viewModel.SavedLayouts.Add(new KeyValuePair<string, byte[]>(args.PromptResult, layoutBytes));
25: IsolatedStoragePersister.SaveState(this.viewModel);
26: }
27: }
28:
29: private void RadMenuItemClear_Click(object sender, RoutedEventArgs e)
30: {
31: this.viewModel.SavedLayouts.Clear();
32: IsolatedStoragePersister.SaveState(this.viewModel);
33: }
As a result the application has its layout configured and you are ready to implement the actual functionality. This is going to be demonstrated in the next blog post.
You can find the source code here.