Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The old NullReferenceException comes back #74

Closed
scorixear opened this issue Sep 12, 2019 · 5 comments
Closed

The old NullReferenceException comes back #74

scorixear opened this issue Sep 12, 2019 · 5 comments

Comments

@scorixear
Copy link

Greetings,
I am currently using version 3.5.12 with net4.8 and I discovered a new version of the old bug in version 3.5.0 with floating anchorables and saving layouts.

further down is the ExceptionWindo.xaml and cs file attached, in which you can reproduce this error.
The main key here is using two dockingManagers for two separate sections within TabControl although I think it can be done with other "Hiding" WPF elements.

To reproduce the error, you have to open this application. detach one of the windows to a floating anchorable and then save the layout. You switch tabs then load the layout (nothing should visually happen) and then switch back to the old tab. Now there is not one but two floating anchorables, and one points to a weirdly null reference.

Correct me, if I am saving these layouts wrong,

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock" x:Class="ExceptionWindow.ExceptionWindow"
        mc:Ignorable="d"
        Title="Exception Window" Height="800" Width="1200">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="20"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Button x:Name="LoadButton" Content="Load Layout" Grid.Row="0" Grid.Column="0" Click="LoadButton_Click"/>
        <Button x:Name="SaveButton" Content="Save Layout" Grid.Row="0" Grid.Column="1" Click="SaveButton_Click"/>
        <TabControl SelectedIndex="0" Grid.Row="1" Grid.ColumnSpan="2">
            <TabItem Header="Tab 1">
                <xcad:DockingManager x:Name="dockingManager1" AllowMixedOrientation="True">

                    <xcad:LayoutRoot>

                        <xcad:LayoutPanel Orientation="Horizontal">


                            <xcad:LayoutAnchorablePaneGroup Orientation="Vertical" DockWidth="40*">

                                <xcad:LayoutAnchorablePane>

                                    <xcad:LayoutAnchorable ContentId="Window1" Title="Window 1" CanHide="False" CanAutoHide="False" CanFloat="True">

                                        <Grid></Grid>
                                    </xcad:LayoutAnchorable>
                                </xcad:LayoutAnchorablePane>

                                <xcad:LayoutAnchorablePane>
                                    <xcad:LayoutAnchorable ContentId="Window2" Title="Window 2" CanAutoHide="False" CanHide="True" CanClose="True">
                                        <Grid></Grid>
                                    </xcad:LayoutAnchorable>
                                </xcad:LayoutAnchorablePane>
                            </xcad:LayoutAnchorablePaneGroup>

                            <xcad:LayoutAnchorablePane DockWidth="60*">
                                <xcad:LayoutAnchorable ContentId="Window3" Title="Window 3" CanHide="True" CanAutoHide="False" CanClose="True">
                                    <Grid></Grid>
                                </xcad:LayoutAnchorable>
                            </xcad:LayoutAnchorablePane>

                        </xcad:LayoutPanel>
                    </xcad:LayoutRoot>
                </xcad:DockingManager>
            </TabItem>
            <TabItem Header="Tab 2">
                <xcad:DockingManager x:Name="dockingManager2" AllowMixedOrientation="True">
                    <xcad:LayoutRoot>
                        <xcad:LayoutPanel Orientation="Horizontal">
                            <xcad:LayoutAnchorablePane DockWidth="25*">
                                <xcad:LayoutAnchorable CanClose="False"  IsActive="True" CanHide="False" ContentId="Window4" Title="Window 4">
                                   <Grid></Grid>
                                </xcad:LayoutAnchorable>
                            </xcad:LayoutAnchorablePane>
                            <xcad:LayoutAnchorablePane DockWidth="75*">
                                <xcad:LayoutAnchorable CanClose="False" CanHide="False" CanAutoHide="False" ContentId="Window5" Title="Window 5">
                                   <Grid></Grid>
                                </xcad:LayoutAnchorable>
                            </xcad:LayoutAnchorablePane>
                        </xcad:LayoutPanel>
                    </xcad:LayoutRoot>
                </xcad:DockingManager>
            </TabItem>
        </TabControl>
    </Grid>
</Window>
using System.Windows;
using Xceed.Wpf.AvalonDock.Layout.Serialization;

namespace ExceptionWindow
{
    /// <summary>
    /// Interaction logic for FrmMain.xaml
    /// </summary>
    public partial class ExceptionWindow : Window
    {

        private XmlLayoutSerializer docking1LayoutSerializer;
        private XmlLayoutSerializer docking2LayoutSerializer;

        public ExceptionWindow()
        {
            //Initialize General UI
            InitializeComponent();
            docking1LayoutSerializer = new XmlLayoutSerializer(dockingManager1);
            docking2LayoutSerializer = new XmlLayoutSerializer(dockingManager2);
        }

        private void LoadButton_Click(object sender, RoutedEventArgs e)
        {
            docking1LayoutSerializer.Deserialize("test-docking1.xml");
            dockingManager1 = docking1LayoutSerializer.Manager;

            docking2LayoutSerializer.Deserialize("test-docking2.xml");
            dockingManager2 = docking2LayoutSerializer.Manager;
        }

        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {

            docking1LayoutSerializer.Serialize("test-docking1.xml");
            docking2LayoutSerializer.Serialize("test-docking2.xml");

        }
    }
}
@Dirkster99
Copy link
Owner

Hi,

thanks for your information. But the report as such is missing the actual error stack trace. I am also not interested in supporting more than one instance of AvalonDock per application... would you please be able to attach a reproducable sample using only one AvalonDock instance with TabItem (you can grab any of the test Apps in this repository) and attach:

  1. the source code to reproduce the problem
  2. a stacktrace (and screenshots of the 2 floating windows) of the exception
  3. step-by-step instructions on how to re-produce the issue (including special settings - we have to use Net4.8 in the client application to reproduce this right?)

Thanks Dirk

@scorixear
Copy link
Author

Hi Dirkster, thanks for the answer. (I am sorry for the delay, but I can only work on working days with this project). Two avalondocks are actually not the problem here ;)

Step-by-Step:

  1. Open the application with the window-code below
  2. Detach one of the windows (for example Window 1) so it is floating
  3. Save the Layout with the button (correct me if I save layouts wrong)
  4. Switch to Tab 2 (reason for that is, that the problem only occurs, when you load a layout of an avalondock which is not visible)
  5. Load the layout via the button
  6. Switch back to Tab 1 and see the following two floating windows:
    the two floating windows

Some nodes:
My application is in Net.4.8 but it is not required, the same bug appears in version 4.0.
The stacktrace points to the DragService. I think the error is not in the DragService. Any interaction with this bugged window will throw an error. It just so happend that I tried to drag it. The exception is also thrown when just closing the main window. But now it is on the LayoutAnchorableFloatingWindowControl.OnClosed method.

StackTrace:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at Xceed.Wpf.AvalonDock.Controls.DragService.GetOverlayWindowHosts() in C:\projects\avalondock\source\Components\Xceed.Wpf.AvalonDock\Controls\DragService.cs:line 195
   at Xceed.Wpf.AvalonDock.Controls.DragService..ctor(LayoutFloatingWindowControl floatingWindow) in C:\projects\avalondock\source\Components\Xceed.Wpf.AvalonDock\Controls\DragService.cs:line 46
   at Xceed.Wpf.AvalonDock.Controls.LayoutFloatingWindowControl.UpdateDragPosition() in C:\projects\avalondock\source\Components\Xceed.Wpf.AvalonDock\Controls\LayoutFloatingWindowControl.cs:line 524
   at Xceed.Wpf.AvalonDock.Controls.LayoutFloatingWindowControl.FilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) in C:\projects\avalondock\source\Components\Xceed.Wpf.AvalonDock\Controls\LayoutFloatingWindowControl.cs:line 377
   at Xceed.Wpf.AvalonDock.Controls.LayoutAnchorableFloatingWindowControl.FilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) in C:\projects\avalondock\source\Components\Xceed.Wpf.AvalonDock\Controls\LayoutAnchorableFloatingWindowControl.cs:line 254
   at System.Windows.Interop.HwndSource.PublicHooksFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
The program '[9352] ***.exe' has exited with code 0 (0x0).
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock" x:Class="ExceptionWindow.ExceptionWindow"
        mc:Ignorable="d"
        Title="Exception Window" Height="800" Width="1200">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="20"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Button x:Name="LoadButton" Content="Load Layout" Grid.Row="0" Grid.Column="0" Click="LoadButton_Click"/>
        <Button x:Name="SaveButton" Content="Save Layout" Grid.Row="0" Grid.Column="1" Click="SaveButton_Click"/>
        <TabControl SelectedIndex="0" Grid.Row="1" Grid.ColumnSpan="2">
            <TabItem Header="Tab 1">
                <xcad:DockingManager x:Name="dockingManager1" AllowMixedOrientation="True">
                    <xcad:LayoutRoot>
                        <xcad:LayoutPanel Orientation="Horizontal">
                            <xcad:LayoutAnchorablePaneGroup Orientation="Vertical" DockWidth="40*">
                                <xcad:LayoutAnchorablePane>
                                    <xcad:LayoutAnchorable ContentId="Window1" Title="Window 1" CanHide="False" CanAutoHide="False" CanFloat="True">
                                        <Grid></Grid>
                                    </xcad:LayoutAnchorable>
                                </xcad:LayoutAnchorablePane>

                                <xcad:LayoutAnchorablePane>
                                    <xcad:LayoutAnchorable ContentId="Window2" Title="Window 2" CanAutoHide="False" CanHide="True" CanClose="True">
                                        <Grid></Grid>
                                    </xcad:LayoutAnchorable>
                                </xcad:LayoutAnchorablePane>
                            </xcad:LayoutAnchorablePaneGroup>

                            <xcad:LayoutAnchorablePane DockWidth="60*">
                                <xcad:LayoutAnchorable ContentId="Window3" Title="Window 3" CanHide="True" CanAutoHide="False" CanClose="True">
                                    <Grid></Grid>
                                </xcad:LayoutAnchorable>
                            </xcad:LayoutAnchorablePane>

                        </xcad:LayoutPanel>
                    </xcad:LayoutRoot>
                </xcad:DockingManager>
            </TabItem>
            <TabItem Header="Tab 2">

                <Grid></Grid>

            </TabItem>
        </TabControl>
    </Grid>
</Window>
using System.Windows;
using Xceed.Wpf.AvalonDock.Layout.Serialization;

namespace ExceptionWindow
{
    /// <summary>
    /// Interaction logic for FrmMain.xaml
    /// </summary>
    public partial class ExceptionWindow : Window
    {

        private XmlLayoutSerializer docking1LayoutSerializer;

        public ExceptionWindow()
        {
            //Initialize General UI
            InitializeComponent();
            docking1LayoutSerializer = new XmlLayoutSerializer(dockingManager1);

        }

        private void LoadButton_Click(object sender, RoutedEventArgs e)
        {
            docking1LayoutSerializer.Deserialize("test-docking1.xml");
            dockingManager1 = docking1LayoutSerializer.Manager;

        }

        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {

            docking1LayoutSerializer.Serialize("test-docking1.xml");

        }
    }
}

@ppalazkov
Copy link
Contributor

ppalazkov commented Sep 17, 2019

I've seen a crash in LayoutAnchorableFloatingWindowControl.OnClosed because of root.Manager = null during root.Manager.RemoveFloatingWindow( this );
Please, take a look to the proposed PR to clear hidden windows
59b6873

@Dirkster99
Copy link
Owner

Hi @ppalazkov and @scorixear

I was finally able to verify the problem - this far I was unable to verify it because the 2nd floating window always appeared on top of the 1st floating window which made it hard to spot the solution. The fix from @ppalazkov works great so I'll be getting this into the next release sometime at the beginning of next week. Thanks for your patience :-)

@ppalazkov: What do you think about this issue and the solution I have so far? I think I should use a list/array as the base of an enumeration instead of the Enumeration as it is currently used in at least 2 places where this issue results in an exception.

Would you resolve this problem in this way as well or can you think of a better solution?

@Dirkster99
Copy link
Owner

The issue is fixed with version 3.5.13

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants