Using the DockingCustomPropertyProvider I save the docking settings. When I try to load them back up, (after I have unpinned a panel) I get the following error: The given key was not present in the dictionary.
using
System;
using
System.Collections.Generic;
using
System.IO;
using
System.Linq;
using
System.Text;
using
Telerik.Windows.Controls;
using
Telerik.Windows.Persistence.Services;
namespace
BasicDockingPersistenceExample
{
public
class
DockingCustomPropertyProvider : ICustomPropertyProvider
{
public
CustomPropertyInfo[] GetCustomProperties()
{
// Create two custom properties to serialize the Layout of the RadDocking and the Content of the RadPanes
return
new
CustomPropertyInfo[]
{
new
CustomPropertyInfo(
"Layout"
,
typeof
(
string
)),
new
CustomPropertyInfo(
"Content"
,
typeof
(List<PaneProxy>)) {AllowCreateInstance =
false
, TreatAsUI =
false
},
};
}
public
void
InitializeObject(
object
context)
{
}
public
object
InitializeValue(CustomPropertyInfo customPropertyInfo,
object
context)
{
if
(customPropertyInfo.Name ==
"Content"
)
{
// See remarks in ProvideValue method:
// provide the values on which the saved properties will be restored upon
RadDocking docking = context
as
RadDocking;
List<PaneProxy> proxies =
new
List<PaneProxy>();
foreach
(RadPane pane
in
this
.GetOrderedPanes(docking).ToArray())
{
proxies.Add(
new
PaneProxy() { Content = pane.Content });
}
return
proxies;
}
return
null
;
}
public
object
ProvideValue(CustomPropertyInfo customPropertyInfo,
object
context)
{
RadDocking docking = context
as
RadDocking;
if
(customPropertyInfo.Name ==
"Layout"
)
{
// let the RadDocking save the layout of the Panes:
return
this
.SaveLayoutAsString(docking);
}
else
if
(customPropertyInfo.Name ==
"Content"
)
{
// create proxies for all of the Panes and save their content
IEnumerable<RadPane> panes =
this
.GetOrderedPanes(docking);
List<PaneProxy> proxies =
new
List<PaneProxy>();
foreach
(RadPane pane
in
panes)
{
proxies.Add(
new
PaneProxy() { Content = pane.Content });
}
return
proxies;
}
return
null
;
}
public
void
RestoreValue(CustomPropertyInfo customPropertyInfo,
object
context,
object
value)
{
if
(customPropertyInfo.Name ==
"Layout"
)
{
// let the RadDocking load the layout of the RadPanes
this
.LoadLayoutFromString(value.ToString(), context
as
RadDocking);
}
else
if
(customPropertyInfo.Name ==
"Content"
)
{
// the PersistenceManager does not re-create UI elements - in this case the Content of the RadPane.
// So, instead of providing a value on which the saved properties will be applied,
// we will use the InitializeValue method.
}
}
private
string
SaveLayoutAsString(RadDocking instance)
{
MemoryStream stream =
new
MemoryStream();
instance.SaveLayout(stream);
stream.Seek(0, SeekOrigin.Begin);
StreamReader reader =
new
StreamReader(stream);
return
reader.ReadToEnd();
}
private
void
LoadLayoutFromString(
string
xml, RadDocking instance)
{
using
(Stream stream =
new
MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
stream.Seek(0, SeekOrigin.Begin);
instance.LoadLayout(stream);
}
}
private
IEnumerable<RadPane> GetOrderedPanes(RadDocking docking)
{
// get the RadPanes always in the same order:
RadPane[] array = docking.Panes.ToArray();
Array.Sort(array,
new
RadPaneComparer());
return
array;
}
}
public
class
RadPaneComparer : IComparer<RadPane>
{
int
IComparer<RadPane>.Compare(RadPane x, RadPane y)
{
// compare RadPanes by their serialization tag:
string
xSerializationTag = RadDocking.GetSerializationTag(x);
string
ySerializationTag = RadDocking.GetSerializationTag(y);
return
xSerializationTag.CompareTo(ySerializationTag);
}
}
public
class
PaneProxy
{
public
object
Content {
get
;
set
; }
}
}
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Linq;
using
System.Text;
namespace
BasicDockingPersistenceExample
{
public
class
MainWindowViewModel : INotifyPropertyChanged
{
public
MainWindowViewModel()
{
}
#region DockPanel pinning properties
private
bool
? _pane2PanelIsPinned =
false
;
public
bool
? Pane2PanelIsPinned
{
get
{
return
_pane2PanelIsPinned; }
set
{
_pane2PanelIsPinned = value;
FirePropertyChanged(
"Pane2PanelIsPinned"
);
}
}
private
bool
? _pane1PanelIsPinned =
false
;
public
bool
? Pane1PanelIsPinned
{
get
{
return
_pane1PanelIsPinned; }
set
{
_pane1PanelIsPinned = value;
FirePropertyChanged(
"Pane1PanelIsPinned"
);
}
}
private
bool
? _pane5PanelIsPinned =
false
;
public
bool
? Pane5PanelIsPinned
{
get
{
return
_pane5PanelIsPinned; }
set
{
_pane5PanelIsPinned = value;
FirePropertyChanged(
"Pane5PanelIsPinned"
);
}
}
private
bool
? _pane3PanelIsPinned =
true
;
public
bool
? Pane3PanelIsPinned
{
get
{
return
_pane3PanelIsPinned; }
set
{
_pane3PanelIsPinned = value;
FirePropertyChanged(
"Pane3PanelIsPinned"
);
}
}
private
bool
? _pane4PanelIsPinned =
true
;
public
bool
? Pane4PanelIsPinned
{
get
{
return
_pane4PanelIsPinned; }
set
{
_pane4PanelIsPinned = value;
FirePropertyChanged(
"Pane4PanelIsPinned"
);
}
}
#endregion
public
event
PropertyChangedEventHandler PropertyChanged;
protected
void
FirePropertyChanged(
string
property)
{
//Should only be called by ViewModel base class. Derived classes should use lambda/LINQ syntax to simplify refactoring
if
(PropertyChanged !=
null
)
PropertyChanged(
this
,
new
PropertyChangedEventArgs(property));
}
}
}
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Windows;
using
System.Windows.Controls;
using
System.Windows.Data;
using
System.Windows.Documents;
using
System.Windows.Input;
using
System.Windows.Media;
using
System.Windows.Media.Imaging;
using
System.Windows.Navigation;
using
System.Windows.Shapes;
using
Telerik.Windows.Controls;
using
Telerik.Windows.Persistence.Services;
using
Telerik.Windows.Persistence.Storage;
namespace
BasicDockingPersistenceExample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public
partial
class
MainWindow : Window
{
public
MainWindow()
{
ServiceProvider.RegisterPersistenceProvider<ICustomPropertyProvider>(
typeof
(RadDocking),
new
DockingCustomPropertyProvider());
this
.DataContext =
new
MainWindowViewModel();
InitializeComponent();
Dispatcher.ShutdownStarted +=
new
EventHandler(DispatcherShutdownStarted);
}
private
void
DispatcherShutdownStarted(
object
sender, EventArgs e)
{
Dispatcher.ShutdownStarted -=
new
EventHandler(DispatcherShutdownStarted);
SaveLayout();
}
private
void
SaveLayout()
{
var storage =
new
IsolatedStorageProvider();
storage.SaveToStorage();
}
private
void
LoadLayout()
{
var storage =
new
IsolatedStorageProvider();
storage.LoadFromStorage();
}
private
void
BuildDockingLoaded(
object
sender, RoutedEventArgs e)
{
LoadLayout();
}
}
}
<
Window
x:Class
=
"BasicDockingPersistenceExample.MainWindow"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
Title
=
"MainWindow"
Height
=
"588"
Width
=
"876"
>
<
telerik:RadDocking
x:Name
=
"BuildDocking"
HorizontalAlignment
=
"Stretch"
VerticalAlignment
=
"Stretch"
Padding
=
"2"
HasDocumentHost
=
"False"
Loaded
=
"BuildDockingLoaded"
telerik:PersistenceManager.StorageId
=
"BuildDocking"
>
<
telerik:RadSplitContainer
Orientation
=
"Horizontal"
InitialPosition
=
"DockedBottom"
>
<
telerik:RadPaneGroup
>
<
telerik:RadPane
x:Name
=
"Pane1Panel"
Header
=
"Pane 1"
telerik:RadDocking.SerializationTag
=
"Pane1Panel"
IsPinned
=
"{Binding Path=Pane1PanelIsPinned, Mode=TwoWay}"
CanUserClose
=
"False"
CanDockInDocumentHost
=
"False"
>
</
telerik:RadPane
>
</
telerik:RadPaneGroup
>
</
telerik:RadSplitContainer
>
<
telerik:RadSplitContainer
Orientation
=
"Horizontal"
InitialPosition
=
"DockedLeft"
>
<
telerik:RadPaneGroup
telerik:ProportionalStackPanel.RelativeSize
=
"200, 300"
>
<
telerik:RadPane
x:Name
=
"Pane2Panel"
Header
=
"Pane 2"
telerik:RadDocking.SerializationTag
=
"Pane2Panel"
IsPinned
=
"{Binding Path=Pane2PanelIsPinned, Mode=TwoWay}"
CanUserClose
=
"False"
CanDockInDocumentHost
=
"False"
>
</
telerik:RadPane
>
</
telerik:RadPaneGroup
>
</
telerik:RadSplitContainer
>
<
telerik:RadSplitContainer
Orientation
=
"Horizontal"
InitialPosition
=
"DockedRight"
MinWidth
=
"300"
>
<
telerik:RadPaneGroup
>
<
telerik:RadPane
Header
=
"Pane 3"
x:Name
=
"Pane3Panel"
telerik:RadDocking.SerializationTag
=
"Pane3Panel"
IsPinned
=
"{Binding Path=Pane3PanelIsPinned, Mode=TwoWay}"
CanUserClose
=
"False"
CanDockInDocumentHost
=
"False"
>
</
telerik:RadPane
>
</
telerik:RadPaneGroup
>
</
telerik:RadSplitContainer
>
<
telerik:RadSplitContainer
Orientation
=
"Vertical"
InitialPosition
=
"DockedTop"
MinHeight
=
"100"
>
<
telerik:RadPaneGroup
>
<
telerik:RadPane
Header
=
"Pane 4"
x:Name
=
"Pane4Panel"
telerik:RadDocking.SerializationTag
=
"Pane4Panel"
IsPinned
=
"{Binding Path=Pane4PanelIsPinned, Mode=TwoWay}"
CanUserClose
=
"False"
CanDockInDocumentHost
=
"False"
>
</
telerik:RadPane
>
</
telerik:RadPaneGroup
>
</
telerik:RadSplitContainer
>
<
telerik:RadSplitContainer
Orientation
=
"Vertical"
InitialPosition
=
"DockedTop"
MinHeight
=
"100"
>
<
telerik:RadPaneGroup
>
<
telerik:RadPane
Header
=
"Pane 5"
x:Name
=
"Pane5Panel"
telerik:RadDocking.SerializationTag
=
"Pane5Panel"
IsPinned
=
"{Binding Path=Pane5PanelIsPinned, Mode=TwoWay}"
CanUserClose
=
"False"
CanDockInDocumentHost
=
"False"
>
</
telerik:RadPane
>
</
telerik:RadPaneGroup
>
</
telerik:RadSplitContainer
>
</
telerik:RadDocking
>
</
Window
>