[Version 2.0] Content disappearing when Deserialize is called

May 9, 2012 at 6:21 PM

When I serialize the following xaml:

        <avalonDock:DockingManager Grid.Row="1" x:Name="DockManager">
            <avalonDock:DockingManager.Theme>
                <avalonDock:VS2010Theme/>
            </avalonDock:DockingManager.Theme>
            <avalonDock:LayoutRoot>
                <avalonDock:LayoutPanel Orientation="Horizontal">
                    <avalonDock:LayoutAnchorablePaneGroup DockWidth="150">
                        <avalonDock:LayoutAnchorablePane>
                            <avalonDock:LayoutAnchorable x:Name="ToolWindow1" Title="Tool Window 1">
                                <TextBox x:Name="txtToolWindow1" Text="Tool Window 1"/>
                            </avalonDock:LayoutAnchorable>
                            <avalonDock:LayoutAnchorable x:Name="ToolWindow2" Title="Tool Window 2">
                                <TextBlock x:Name="txtToolWindow2" Text="Tool Window 2"/>
                            </avalonDock:LayoutAnchorable>
                        </avalonDock:LayoutAnchorablePane>
                    </avalonDock:LayoutAnchorablePaneGroup>
                </avalonDock:LayoutPanel>
            </avalonDock:LayoutRoot>
        </avalonDock:DockingManager>

I get the following serialized xml:

<?xml version="1.0" encoding="utf-16"?>
<LayoutRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <RootPanel Orientation="Horizontal">
    <LayoutAnchorablePaneGroup Orientation="Horizontal">
      <LayoutAnchorablePane>
        <LayoutAnchorable Title="Tool Window 1" IsSelected="True" ContentId="txtToolWindow1" />
        <LayoutAnchorable Title="Tool Window 2" ContentId="txtToolWindow2" />
      </LayoutAnchorablePane>
    </LayoutAnchorablePaneGroup>
  </RootPanel>
  <TopSide />
  <RightSide />
  <LeftSide />
  <BottomSide />
  <FloatingWindows />
  <Hidden />
</LayoutRoot>

 

The problem is that when I Deserialize the xml the TextBox and TextBlock disappear.

Here is the code for my save/restore:

	private string lastLayout = "";

	private void btnSaveLayout_Click(object sender, RoutedEventArgs e)
	{
		StringBuilder sb = new StringBuilder();
		using (StringWriter sw = new StringWriter(sb))
		{
			var serializer = new XmlLayoutSerializer(DockManager);
			serializer.Serialize(sw);
			sw.Flush();
			lastLayout = sb.ToString();
		}
	}

	private void btnRestoreLayout_Click(object sender, RoutedEventArgs e)
	{
		StringReader sr = new StringReader(lastLayout);
		
		var serializer = new XmlLayoutSerializer(DockManager);
		serializer.Deserialize(sr);
	}

Is there something I'm missing?  The layout does restore as I expect it to, just the content no longer exists.  This is with build 91056

Thanks,
Brian 

May 10, 2012 at 11:41 PM
Edited May 10, 2012 at 11:46 PM

I ended up adding a LayoutSerializationCallback that fixed the problem but it still feels pretty hacky to me.  This is something that was handled automatically in 1.3 and I thought it made sense in 2.0 for it to work the same.  For me it works as I know all my content has a unique name but YMMV.

 

private void btnRestoreLayout_Click(object sender, RoutedEventArgs e)
{
	if(!DockManager.IsLoaded)
		return;
	
	StringReader sr = new StringReader(lastLayout);
	
	var serializer = new XmlLayoutSerializer(DockManager);
	serializer.LayoutSerializationCallback += (s, args) =>
		{
			args.Content = Application.Current.MainWindow.FindName(args.Model.ContentId);
		};
	serializer.Deserialize(sr);
}
May 11, 2012 at 9:53 AM

In version 1.3, AvalonDock used the control Name to automatically re-loaded contents during deserialization. Even if it was pretty functional, it lead to perfomance issues because AD loaded contents during deseralization even if that contents were not actually shown.
Using version 2.0 you can always use the method you describe above but instead of load the full control you could place a dummy control that can be than fully loaded when layout IsSelected property becames true.

Said that version 2.0 now support MVVM deserialization too. For a sample on how to load a layout using MVVM look at latest sources(MVVMTestApp) that I just uploaded.

Thanks

Feb 16, 2014 at 1:51 PM
Edited Feb 16, 2014 at 1:54 PM
Just saw this post. Actually, just in general, this somewhat answers a puzzling question I've got. When a UI restores layout, how to approach reconnecting Model and/or ViewModel with the restored layout (View).

I'm sure there are as many approaches to this as there are minutes in the day, particularly when model could involve distributed services (i.e. WCF), database repository (i.e. ORM), or even simply files and folders in the file system. Interested to learn some insights, read tutorials on this, etc.

Instead of specifying sort of the academic examples in the Window XAML itself, is it possible to derive more specialized document and tool controls for the sorts of data, behavior, and view that we want to save/restore?

Thank ye...