Home Forums WPF controls Other WPF controls AvalonDock: NullReferenceException when restoring state w/ dynamic Anchorables

Mots-clés : 

4 sujets de 1 à 4 (sur un total de 4)
  • Auteur
  • rabjen-iwes
    Post count: 8
    #44509 |


    I have the NullReferenceException problem when restoring state again.

    I derive my anchorables from this class:

        public abstract class AbstractPanel {
            private Visibility _visibility;
            public virtual string ContentId { get { return GetType().AssemblyQualifiedName; } }
            public abstract string Title { get; }
            public abstract FrameworkElement UIElement { get; }
            public Visibility Visibility {
                get {
                    return _visibility;
                set {
                    var oldVis = Visibility;
                    _visibility = value;
                    if(oldVis != Visibility) {
            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged(string propertyName) {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    Right at the start, in my App.xaml.cs, I collect my panels (I am using MEF):

                foreach(var panel in allServices
                    .SelectMany(c => c.Panels)) {
                    SimpleIoc.Default.Register<AbstractPanel>(() => panel, panel.ContentId, true);

    In my XAML, I registered it correctly:

                            <Style TargetType="{x:Type xcad:LayoutAnchorableItem}">
                                <Setter Property="Title" Value="{Binding Model.Title}"/>
                                <Setter Property="ContentId" Value="{Binding Model.ContentId}" />
                                <Setter Property="Visibility" Value="{Binding Model.Visibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

    Right at the start of the ViewModel, I load the anchorables accordingly:

    Anchorables = SimpleIoc.Default.GetAllCreatedInstances<AbstractPanel>().ToArray();

    When saving a layout, the generated XML looks OK:

    <?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">
        <LayoutAnchorablePane DockWidth="188" FloatingWidth="200" FloatingHeight="519" FloatingLeft="87" FloatingTop="454">
          <LayoutAnchorable AutoHideMinWidth="100" AutoHideMinHeight="100" Title="Measurements" IsSelected="True" ContentId="Measurements" FloatingLeft="87" FloatingTop="454" FloatingWidth="200" FloatingHeight="519" LastActivationTimeStamp="01/26/2017 23:10:05" PreviousContainerId="e19e3aa6-8537-4dca-b9c6-d489b756f92d" PreviousContainerIndex="0" />
        <LayoutPanel Orientation="Horizontal">
          <LayoutDocumentPaneGroup Orientation="Horizontal">
            <LayoutDocumentPane />
        <LayoutAnchorablePane Id="e19e3aa6-8537-4dca-b9c6-d489b756f92d" DockWidth="200">
          <LayoutAnchorable AutoHideMinWidth="100" AutoHideMinHeight="100" Title="All Channels" IsSelected="True" ContentId="All Channels" LastActivationTimeStamp="01/26/2017 23:10:04" />
      <TopSide />
      <RightSide />
      <LeftSide />
      <BottomSide />
      <FloatingWindows />
      <Hidden />

    But, when deserializing this (the anchorables list is already populated), I get the NullReferenceException.

    What is going wrong here?

    Post count: 8


    This is the stack trace:

    System.NullReferenceException was unhandled by user code
      Message=Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
           bei Xceed.Wpf.AvalonDock.Controls.LayoutItem.get_View()
           bei Xceed.Wpf.AvalonDock.DockingManager.RemoveViewFromLogicalChild(LayoutContent layoutContent)
           bei Xceed.Wpf.AvalonDock.DockingManager.DetachAnchorablesSource(LayoutRoot layout, IEnumerable anchorablesSource)
           bei Xceed.Wpf.AvalonDock.DockingManager.OnLayoutChanged(LayoutRoot oldLayout, LayoutRoot newLayout)
           bei Xceed.Wpf.AvalonDock.DockingManager.OnLayoutChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
           bei System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
           bei System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
           bei System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
           bei System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
           bei System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
           bei System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
           bei Xceed.Wpf.AvalonDock.DockingManager.set_Layout(LayoutRoot value)
           bei Xceed.Wpf.AvalonDock.Layout.Serialization.XmlLayoutSerializer.Deserialize(TextReader reader)
           bei My.App.ViewModel.Behavior.AvalonDockLayoutSerializer.LoadLayout(DockingManager dm, String layoutXml) in C:\Somewhere\MyApp\ViewModel\Behavior\AvalonDockLayoutSerializer.cs:Zeile 108.
           bei My.App.ViewModel.MainViewModel.<>c__DisplayClass3_1.<LoadLayout>b__1() in C:\Somewhere\MyApp\ViewModel\MainViewModel.cs:Zeile 46.
           bei System.Windows.Threading.DispatcherOperation.InvokeDelegateCore()
           bei System.Windows.Threading.DispatcherOperation.InvokeImpl()

    I got it to work in the meantime, with a crude hack using reflection.

    This is what I do:

            public static void LoadLayout(this DockingManager dm, string layoutXml) {
                // Walk down the layout and gather the LayoutContent elements.
                // AD bails out when it tries to invoke RemoveViewFromLogicalChild
                // on them.
                var l = GatherLayoutContent(dm.Layout).ToArray();
                // Remove the views by force
                foreach(var x in l) {
                        .GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)
                        .Where(m => m.Name.Equals("RemoveViewFromLogicalChild"))
                        .Invoke(dm, new object[] { x });
                // Now, the deserialization works
                using(var sr = new StringReader(layoutXml)) {
                    var ser = new XmlLayoutSerializer(dm);
            private static IEnumerable<LayoutContent> GatherLayoutContent(ILayoutElement le) {
                if(le is LayoutContent) {
                    yield return (LayoutContent)le;
                IEnumerable<ILayoutElement> children = new ILayoutElement[0];
                if(le is LayoutRoot) {
                    children = ((LayoutRoot)le).Children;
                } else if(le is LayoutPanel) {
                    children = ((LayoutPanel)le).Children;
                } else if(le is LayoutDocumentPaneGroup) {
                    children = ((LayoutDocumentPaneGroup)le).Children;
                } else if(le is LayoutAnchorablePane) {
                    children = ((LayoutAnchorablePane)le).Children;
                } else if(le is LayoutDocumentPane) {
                    children = ((LayoutDocumentPane)le).Children;
                foreach(var child in children) {
                    foreach(var x in GatherLayoutContent(child)) {
                        yield return x;

    Needless to say, I want to get rid of this hack. So, did I find a bug or am I missing something?

    Fawzi [Xceed]
    Post count: 722


    Can you submit a sample so we can reproduce your issue so that we could have a closer look. You may send it to: support@xceed.com

    Post count: 8

    I just wanted to give a followup that I got it to work now. I didn’t send you demo code because this problem occurred in company code I am not allowed to give away.

    I still don’t know what exactly was the culprit, but I redesigned some parts of my application the following way:

    – I put my Anchorable-specific stuff in an interface IPanel that has all the necessary things like the title, Content ID, and a property referencing a FrameworkElement that displays the actual panel
    – I created an AnchorableViewModel that has a property which is a reference to my IPanel and a Visibility property
    – this AnchorableViewModel is now in the same assembly as the one where I construct the Dock (my former Panel class I directly used as the view model was defined in another assembly)
    – I wire up the AnchorableViewModel accordingly in XAML

    Plus, since I do all my UI stuff highly asynchronously with a lot of async/await and Tasks, and using Dispatcher.InvokeAsync a lot to update my ObservableCollections, I cleaned that part up, too. maybe there was some race condition.

4 sujets de 1 à 4 (sur un total de 4)
  • Vous devez être connecté pour répondre à ce sujet.