Hidden tool windows don't restore to same location when using lazy loading

Docking/MDI for WPF Forum

Posted 8 years ago by Keith I
Version: 11.2.0553
Platform: .NET 4.0
Environment: Windows 7 (64-bit)
Avatar

Hi,

With the .553 release the following small problem has been introduced.

- Run the Docking -> Lazy Loading sample

- Click File -> Save Layout

- Click File -> Load Layout several times.

You will notice that the Toolbox tool window on the left moves down the screen each time you load the layout. The problem seems to occur regardless of which side the tool window is docked to.

Regards,

Keith

Comments (6)

Answer - Posted 8 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Keith,

Thank you for reporting this issue, we have uploaded a hotfix for build 553. Please redownload it to get the fix.


Actipro Software Support

Posted 8 years ago by Keith I
Avatar

Thank you very much for your quick response. The hotfix has fixed the problem.

Keith

Posted 8 years ago by Keith I
Avatar

It seems I was a little premature saying that the hotfix has fixed the problem, as that doesn't seem to be the case. The tool windows are still moving down the screen each time I start my application. However, I can no longer reproduce this using the sample browser.

I am saving my layout to a file and loading the layout from the file in the constructor of my window, but other than that I can't see any real difference with what I'm doing to what the sample does. I am certain that I am using the hotfix files in my application.

Do you have any ideas as to what the problem could be?

Regards,

Keith

Posted 8 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Keith,

I'm not sure what the difference could be, but you should not be saving the layout in the constructor. That should be done in the Window's Closing event. If you can try to trim down your application (e.g. remove content from DocumentWindows and ToolWindows) so that you can send it to us, then we can take a look.


Actipro Software Support

Posted 8 years ago by Keith I
Avatar

It seems that saving the layout to a file is the problem, I have modified your sample application to show this.

Replace the LayoutLazyLoading\MainWindow.xaml.cs file with the code below. Then just run the sample browser and run the Docking -> Lazy Loading sample. You just need to immediately close the Lazy Loading window and then open it again (you don't need to use any of the menu options). Do this repeatedly and you will see that the Toolbox tool window moves down the screen.

Regards,

Keith

using System;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using ActiproSoftware.Windows.Controls.Docking;
using ActiproSoftware.Windows.Controls.Docking.Serialization;

namespace ActiproSoftware.Windows.ProductSamples.DockingSamples.QuickStart.LayoutLazyLoading {

    /// <summary>
    /// Provides the main window for this sample.
    /// </summary>
    public partial class MainWindow : System.Windows.Window {

        private bool isLoadingLayout = false;
        private DockSiteLayoutSerializer layoutSerializer;

        /////////////////////////////////////////////////////////////////////////////////////////////////////
        // OBJECT
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Initializes an instance of the <c>MainWindow</c> class.
        /// </summary>
        public MainWindow() {
            InitializeComponent();

            // Create layout serializer
            this.layoutSerializer = new DockSiteLayoutSerializer()
            {
                SerializationBehavior = DockSiteSerializationBehavior.All,
                ToolWindowDeserializationBehavior = DockingWindowDeserializationBehavior.LazyLoad
            };

            // Load the persisted layout
            this.LoadLayout();

            // Attach to the loaded event
            this.Loaded += new RoutedEventHandler(OnLoaded);
            this.Closing += new CancelEventHandler(OnClosing);
        }

        /////////////////////////////////////////////////////////////////////////////////////////////////////
        // NON-PUBLIC PROCEDURES
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Creates the content for a programmatic tool window.
        /// </summary>
        /// <returns>The content for a programmatic tool window.</returns>
        private static UIElement CreateContent() {
            return new TextBox() {
                BorderThickness = new Thickness(),
                IsReadOnly = true,
                Text = "This ToolWindow was programmatically created in the code-behind."
            };
        }

        /// <summary>
        /// Loads the layout from a <see cref="TextBox"/>.
        /// </summary>
        private void LoadLayout()
        {
            string dockSiteLayout = string.Empty;

            try
            {
                string dockFileName = @"C:\Temp\Actipro.layout";
                if (File.Exists(dockFileName))
                {
                    dockSiteLayout = File.ReadAllText(dockFileName);
                    this.isLoadingLayout = true;
                    this.layoutSerializer.LoadFromString(dockSiteLayout, dockSite);
                } // End if
            } // End try
            catch (Exception e)
            {
            } // End catch
            finally
            {
                this.isLoadingLayout = false;
            }
        } // End of method

        /// <summary>
        /// Occurs when the <c>Activate.Programmatic ToolWindow 1</c> menu item is clicked.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
        private void OnActivateProgrammaticToolWindow1Click(object sender, RoutedEventArgs e) {
            ToolWindow toolWindow = this.dockSite.ToolWindows["programmaticToolWindow1"];
            if (toolWindow == null) {
                // Create the tool window content
                TextBox textBox = new TextBox() {
                    BorderThickness = new Thickness(),
                    IsReadOnly = true,
                    Text = "This ToolWindow was programmatically created in the code-behind."
                };

                // Create the tool window
                toolWindow = new ToolWindow(this.dockSite, "programmaticToolWindow1", "Programmatic ToolWindow 1",
                    new BitmapImage(new Uri("/Resources/Images/Properties16.png", UriKind.Relative)), textBox);

                // Change the menu item's header
                this.activeProgrammaticToolWindow1.Header = "Activate Programmatic ToolWindow 1";
            }

            toolWindow.Activate();
        }

        /// <summary>
        /// Occurs when the <c>Activate.Programmatic ToolWindow 2</c> menu item is clicked.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
        private void OnActivateProgrammaticToolWindow2Click(object sender, RoutedEventArgs e) {
            ToolWindow toolWindow = this.dockSite.ToolWindows["programmaticToolWindow2"];
            if (toolWindow == null) {
                // Create and register the tool window
                toolWindow = new CustomToolWindow() {
                    Name = "programmaticToolWindow2"
                };
                this.dockSite.ToolWindows.Add(toolWindow);

                // Change the menu item's header
                this.activeProgrammaticToolWindow2.Header = "Activate Programmatic ToolWindow 2";
            }

            toolWindow.Activate();
        }

        /// <summary>
        /// Occurs when the sample is closed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="CancelEventArgs"/> instance containing the event data.</param>
        private void OnClosing(object sender, CancelEventArgs e) {
            this.SaveLayout();
        }

        /// <summary>
        /// Occurs when the <c>File.Load Layout</c> menu item is clicked.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
        private void OnFileLoadLayoutMenuItemClick(object sender, RoutedEventArgs e) {
            this.LoadLayout();
            MessageBox.Show("Layout loaded from static member variable.");
        }

        /// <summary>
        /// Occurs when the <c>File.Save Layout</c> menu item is clicked.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
        private void OnFileSaveLayoutMenuItemClick(object sender, RoutedEventArgs e) {
            this.SaveLayout();
            MessageBox.Show("Layout saved to static member variable.");
        }

        /// <summary>
        /// Occurs when the sample is loaded.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
        private void OnLoaded(object sender, RoutedEventArgs e) {
            // Invoke so that we can ensure everything is properly loaded before persisting the layout... even from the control's
            //   Loaded event handler, property values may not yet be properly set from the XAML load
            this.Dispatcher.BeginInvoke(DispatcherPriority.Send, (DispatcherOperationCallback)delegate(object arg) {
                // Activate the first document
                if (dockSite.Documents.Count > 0)
                    dockSite.Documents[0].Activate();
                return null;
            }, null);
        }

        /// <summary>
        /// Saves the layout to a <see cref="TextBox"/>.
        /// </summary>
        private void SaveLayout() {
            if (this.isLoadingLayout)
                return;

            string dockSiteLayout = layoutSerializer.SaveToString(dockSite);
            try
            {
                // Save the dock layout
                File.WriteAllText
                    (@"C:\Temp\Actipro.layout",
                    this.layoutSerializer.SaveToString(dockSite));
            } // End try
            catch (Exception e)
            {
            } // End catch
        }

    }
}
Answer - Posted 8 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Keith,

Thanks for reporting this. It appears to ahve to do with loading the layout before the DockSite is fully loaded. We have corrected this for the next maintenance release.


Actipro Software Support

The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.