Browse Source

-Bug fix when restoring layout from xml. all of the "Sides" like leftside and rightside objects were being nulled out causing null reference exceptions when you tried to "unpin" a panel on one of the sides.

pull/1271/head
Paul J Aicher 9 years ago
parent
commit
8fa3191ea9
  1. 479
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutRoot.cs

479
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Layout/LayoutRoot.cs

@ -17,12 +17,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Collections.ObjectModel;
using System.Windows.Markup;
using System.Xml.Serialization;
using Standard;
using System.Xml;
using System.Xml.Schema;
@ -33,7 +30,7 @@ namespace Xceed.Wpf.AvalonDock.Layout
public class LayoutRoot : LayoutElement, ILayoutContainer, ILayoutRoot, IXmlSerializable
{
public LayoutRoot()
{
{
RightSide = new LayoutAnchorSide();
LeftSide = new LayoutAnchorSide();
TopSide = new LayoutAnchorSide();
@ -159,7 +156,7 @@ namespace Xceed.Wpf.AvalonDock.Layout
public ObservableCollection<LayoutFloatingWindow> FloatingWindows
{
get
get
{
if (_floatingWindows == null)
{
@ -167,7 +164,7 @@ namespace Xceed.Wpf.AvalonDock.Layout
_floatingWindows.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_floatingWindows_CollectionChanged);
}
return _floatingWindows;
return _floatingWindows;
}
}
@ -181,7 +178,7 @@ namespace Xceed.Wpf.AvalonDock.Layout
if (element.Parent == this)
element.Parent = null;
}
}
}
if (e.NewItems != null && (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add ||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace))
@ -326,15 +323,15 @@ namespace Xceed.Wpf.AvalonDock.Layout
get
{
return 5 +
(_floatingWindows != null ? _floatingWindows.Count : 0) +
(_hiddenAnchorables != null ? _hiddenAnchorables.Count : 0);
(_floatingWindows != null ? _floatingWindows.Count : 0) +
(_hiddenAnchorables != null ? _hiddenAnchorables.Count : 0);
}
}
#endregion
#region ActiveContent
[field:NonSerialized]
[field: NonSerialized]
private WeakReference _activeContent = null;
private bool _activeContentSet = false;
@ -452,7 +449,7 @@ namespace Xceed.Wpf.AvalonDock.Layout
exitFlag = true;
//for each content that references via PreviousContainer a disconnected Pane set the property to null
foreach (var content in this.Descendents().OfType<ILayoutPreviousContainer>().Where(c => c.PreviousContainer != null &&
foreach (var content in this.Descendents().OfType<ILayoutPreviousContainer>().Where(c => c.PreviousContainer != null &&
(c.PreviousContainer.Parent == null || c.PreviousContainer.Parent.Root != this)))
{
content.PreviousContainer = null;
@ -662,288 +659,280 @@ namespace Xceed.Wpf.AvalonDock.Layout
public event EventHandler<LayoutElementEventArgs> ElementRemoved;
#endregion
#endregion
public XmlSchema GetSchema()
{
return null;
return null;
}
public void ReadXml( XmlReader reader )
public void ReadXml(XmlReader reader)
{
reader.MoveToContent();
if( reader.IsEmptyElement )
{
reader.Read();
return;
}
reader.MoveToContent();
if (reader.IsEmptyElement)
{
reader.Read();
return;
}
var layoutPanelElements = ReadRootPanel( reader );
if( layoutPanelElements != null )
{
//Create the RootPanel with the first child
RootPanel = new LayoutPanel( layoutPanelElements.First() );
//Add all children to RootPanel
for( int i = 1; i < layoutPanelElements.Count; ++i )
var layoutPanelElements = ReadRootPanel(reader);
if (layoutPanelElements != null)
{
RootPanel.Children.Add( layoutPanelElements[ i ] );
//Create the RootPanel with the first child
RootPanel = new LayoutPanel(layoutPanelElements.First());
//Add all children to RootPanel
for (int i = 1; i < layoutPanelElements.Count; ++i)
{
RootPanel.Children.Add(layoutPanelElements[i]);
}
}
}
TopSide = ( LayoutAnchorSide )ReadElement( reader );
if( TopSide != null )
{
TopSide.Children.Add( ( LayoutAnchorGroup )ReadElement( reader ) );
reader.Read();
}
RightSide = ( LayoutAnchorSide )ReadElement( reader );
if( RightSide != null )
{
RightSide.Children.Add( ( LayoutAnchorGroup )ReadElement( reader ) );
reader.Read();
}
LeftSide = ( LayoutAnchorSide )ReadElement( reader );
if( LeftSide != null )
{
LeftSide.Children.Add( ( LayoutAnchorGroup )ReadElement( reader ) );
reader.Read();
}
BottomSide = ( LayoutAnchorSide )ReadElement( reader );
if( BottomSide != null )
{
BottomSide.Children.Add( ( LayoutAnchorGroup )ReadElement( reader ) );
reader.Read();
}
TopSide = GetLayoutAnchorSide(reader);
RightSide = GetLayoutAnchorSide(reader);
LeftSide = GetLayoutAnchorSide(reader);
BottomSide = GetLayoutAnchorSide(reader);
FloatingWindows.Clear();
var floatingWindows = ReadElementList( reader );
foreach( var floatingWindow in floatingWindows )
{
FloatingWindows.Add( ( LayoutFloatingWindow )floatingWindow );
}
FloatingWindows.Clear();
var floatingWindows = ReadElementList(reader);
foreach (var floatingWindow in floatingWindows)
{
FloatingWindows.Add((LayoutFloatingWindow)floatingWindow);
}
Hidden.Clear();
var hidden = ReadElementList( reader );
foreach( var hiddenObject in hidden )
{
Hidden.Add( ( LayoutAnchorable )hiddenObject );
}
Hidden.Clear();
var hidden = ReadElementList(reader);
foreach (var hiddenObject in hidden)
{
Hidden.Add((LayoutAnchorable)hiddenObject);
}
}
private List<ILayoutPanelElement> ReadRootPanel( XmlReader reader )
private LayoutAnchorSide GetLayoutAnchorSide(XmlReader reader)
{
var result = new List<ILayoutPanelElement>();
var side = (LayoutAnchorSide)ReadElement(reader);
if (side != null)
{
side.Children.Add((LayoutAnchorGroup)ReadElement(reader));
reader.Read();
}
var startElementName = reader.LocalName;
reader.Read();
if( reader.LocalName.Equals(startElementName) && (reader.NodeType == XmlNodeType.EndElement) )
{
return null;
}
return side ?? new LayoutAnchorSide();
}
while( reader.NodeType == XmlNodeType.Whitespace )
{
reader.Read();
}
private List<ILayoutPanelElement> ReadRootPanel(XmlReader reader)
{
var result = new List<ILayoutPanelElement>();
if( reader.LocalName.Equals("RootPanel"))
{
var startElementName = reader.LocalName;
reader.Read();
if (reader.LocalName.Equals(startElementName) && (reader.NodeType == XmlNodeType.EndElement))
{
return null;
}
while( true )
while (reader.NodeType == XmlNodeType.Whitespace)
{
//Read all RootPanel children
var element = ReadElement( reader ) as ILayoutPanelElement;
if( element != null )
{
result.Add( element );
}
else if( reader.NodeType == XmlNodeType.EndElement )
{
break;
}
reader.Read();
}
}
reader.ReadEndElement();
if (reader.LocalName.Equals("RootPanel"))
{
reader.Read();
return result;
while (true)
{
//Read all RootPanel children
var element = ReadElement(reader) as ILayoutPanelElement;
if (element != null)
{
result.Add(element);
}
else if (reader.NodeType == XmlNodeType.EndElement)
{
break;
}
}
}
reader.ReadEndElement();
return result;
}
private List<object> ReadElementList( XmlReader reader )
private List<object> ReadElementList(XmlReader reader)
{
var resultList = new List<object>();
if( reader.IsEmptyElement )
{
reader.Read();
return resultList;
}
var resultList = new List<object>();
var startElementName = reader.LocalName;
reader.Read();
if( reader.LocalName.Equals(startElementName) && (reader.NodeType == XmlNodeType.EndElement) )
{
return null;
}
if (reader.IsEmptyElement)
{
reader.Read();
return resultList;
}
while( reader.NodeType == XmlNodeType.Whitespace )
{
var startElementName = reader.LocalName;
reader.Read();
}
if (reader.LocalName.Equals(startElementName) && (reader.NodeType == XmlNodeType.EndElement))
{
return null;
}
while( true )
{
var result = ReadElement( reader ) as LayoutFloatingWindow;
if( result == null )
while (reader.NodeType == XmlNodeType.Whitespace)
{
break;
reader.Read();
}
resultList.Add( result );
}
while (true)
{
var result = ReadElement(reader) as LayoutFloatingWindow;
if (result == null)
{
break;
}
resultList.Add(result);
}
reader.ReadEndElement();
reader.ReadEndElement();
return resultList;
return resultList;
}
private object ReadElement( XmlReader reader )
private object ReadElement(XmlReader reader)
{
if( reader.NodeType == XmlNodeType.EndElement )
{
return null;
}
if (reader.NodeType == XmlNodeType.EndElement)
{
return null;
}
while( reader.NodeType == XmlNodeType.Whitespace )
{
reader.Read();
}
XmlSerializer serializer;
switch( reader.LocalName )
{
case "LayoutAnchorablePaneGroup":
serializer = new XmlSerializer( typeof( LayoutAnchorablePaneGroup ) );
break;
case "LayoutAnchorablePane":
serializer = new XmlSerializer( typeof( LayoutAnchorablePane ) );
break;
case "LayoutAnchorable":
serializer = new XmlSerializer( typeof( LayoutAnchorable ) );
break;
case "LayoutDocumentPaneGroup":
serializer = new XmlSerializer( typeof( LayoutDocumentPaneGroup ) );
break;
case "LayoutDocumentPane":
serializer = new XmlSerializer( typeof( LayoutDocumentPane ) );
break;
case "LayoutDocument":
serializer = new XmlSerializer( typeof( LayoutDocument ) );
break;
case "LayoutAnchorGroup":
serializer = new XmlSerializer( typeof( LayoutAnchorGroup ) );
break;
case "LayoutPanel":
serializer = new XmlSerializer( typeof( LayoutPanel ) );
break;
case "LayoutDocumentFloatingWindow":
serializer = new XmlSerializer( typeof( LayoutDocumentFloatingWindow ) );
break;
case "LayoutAnchorableFloatingWindow":
serializer = new XmlSerializer( typeof( LayoutAnchorableFloatingWindow ) );
break;
case "LeftSide":
case "RightSide":
case "TopSide":
case "BottomSide":
if( reader.IsEmptyElement )
{
while (reader.NodeType == XmlNodeType.Whitespace)
{
reader.Read();
return null;
}
reader.Read();
return new LayoutAnchorSide();
default:
var type = LayoutRoot.FindType( reader.LocalName );
if( type == null )
{
throw new ArgumentException( "AvalonDock.LayoutRoot doesn't know how to deserialize " + reader.LocalName );
}
serializer = new XmlSerializer( type );
break;
}
return serializer.Deserialize( reader );
}
public void WriteXml( XmlWriter writer )
{
writer.WriteStartElement( "RootPanel" );
if( RootPanel != null )
{
RootPanel.WriteXml( writer );
}
writer.WriteEndElement();
writer.WriteStartElement( "TopSide" );
if( TopSide != null )
{
TopSide.WriteXml( writer );
}
writer.WriteEndElement();
writer.WriteStartElement( "RightSide" );
if( RightSide != null )
{
RightSide.WriteXml( writer );
}
writer.WriteEndElement();
writer.WriteStartElement( "LeftSide" );
if( LeftSide != null )
{
LeftSide.WriteXml( writer );
}
writer.WriteEndElement();
writer.WriteStartElement( "BottomSide" );
if( BottomSide != null )
{
BottomSide.WriteXml( writer );
}
writer.WriteEndElement();
// Write all floating windows (can be LayoutDocumentFloatingWindow or LayoutAnchorableFloatingWindow).
// To prevent "can not create instance of abstract type", the type is retrieved with GetType().Name
writer.WriteStartElement( "FloatingWindows" );
foreach( var layoutFloatingWindow in FloatingWindows )
{
writer.WriteStartElement( layoutFloatingWindow.GetType().Name );
layoutFloatingWindow.WriteXml( writer );
}
XmlSerializer serializer;
switch (reader.LocalName)
{
case "LayoutAnchorablePaneGroup":
serializer = new XmlSerializer(typeof(LayoutAnchorablePaneGroup));
break;
case "LayoutAnchorablePane":
serializer = new XmlSerializer(typeof(LayoutAnchorablePane));
break;
case "LayoutAnchorable":
serializer = new XmlSerializer(typeof(LayoutAnchorable));
break;
case "LayoutDocumentPaneGroup":
serializer = new XmlSerializer(typeof(LayoutDocumentPaneGroup));
break;
case "LayoutDocumentPane":
serializer = new XmlSerializer(typeof(LayoutDocumentPane));
break;
case "LayoutDocument":
serializer = new XmlSerializer(typeof(LayoutDocument));
break;
case "LayoutAnchorGroup":
serializer = new XmlSerializer(typeof(LayoutAnchorGroup));
break;
case "LayoutPanel":
serializer = new XmlSerializer(typeof(LayoutPanel));
break;
case "LayoutDocumentFloatingWindow":
serializer = new XmlSerializer(typeof(LayoutDocumentFloatingWindow));
break;
case "LayoutAnchorableFloatingWindow":
serializer = new XmlSerializer(typeof(LayoutAnchorableFloatingWindow));
break;
case "LeftSide":
case "RightSide":
case "TopSide":
case "BottomSide":
if (reader.IsEmptyElement)
{
reader.Read();
return null;
}
reader.Read();
return new LayoutAnchorSide();
default:
var type = LayoutRoot.FindType(reader.LocalName);
if (type == null)
{
throw new ArgumentException("AvalonDock.LayoutRoot doesn't know how to deserialize " + reader.LocalName);
}
serializer = new XmlSerializer(type);
break;
}
return serializer.Deserialize(reader);
}
public void WriteXml(XmlWriter writer)
{
writer.WriteStartElement("RootPanel");
if (RootPanel != null)
{
RootPanel.WriteXml(writer);
}
writer.WriteEndElement();
writer.WriteStartElement("TopSide");
if (TopSide != null)
{
TopSide.WriteXml(writer);
}
writer.WriteEndElement();
writer.WriteStartElement("RightSide");
if (RightSide != null)
{
RightSide.WriteXml(writer);
}
writer.WriteEndElement();
writer.WriteStartElement("LeftSide");
if (LeftSide != null)
{
LeftSide.WriteXml(writer);
}
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.WriteStartElement( "Hidden" );
foreach( var layoutAnchorable in Hidden )
{
layoutAnchorable.WriteXml( writer );
}
writer.WriteEndElement();
writer.WriteStartElement("BottomSide");
if (BottomSide != null)
{
BottomSide.WriteXml(writer);
}
writer.WriteEndElement();
// Write all floating windows (can be LayoutDocumentFloatingWindow or LayoutAnchorableFloatingWindow).
// To prevent "can not create instance of abstract type", the type is retrieved with GetType().Name
writer.WriteStartElement("FloatingWindows");
foreach (var layoutFloatingWindow in FloatingWindows)
{
writer.WriteStartElement(layoutFloatingWindow.GetType().Name);
layoutFloatingWindow.WriteXml(writer);
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.WriteStartElement("Hidden");
foreach (var layoutAnchorable in Hidden)
{
layoutAnchorable.WriteXml(writer);
}
writer.WriteEndElement();
}
internal static Type FindType( string name )
internal static Type FindType(string name)
{
foreach( var assembly in AppDomain.CurrentDomain.GetAssemblies() )
{
foreach( var type in assembly.GetTypes() )
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
if( type.Name.Equals( name ) )
return type;
foreach (var type in assembly.GetTypes())
{
if (type.Name.Equals(name))
return type;
}
}
}
return null;
return null;
}
#if TRACE

Loading…
Cancel
Save