Current filter:
                                You should refresh the page.
                                  • Hi,

                                    This issue has plagued us for a long time, and I'm trying to solve it now as I now have a repro case but I can't fix it. The scenario:
                                    Our winforms application uses your controls for its UI, and among it a Dockmanager and several panels. These panels are created in the winforms designer and are created in the InitializeComponent method of the form. This all works fine.

                                    When the application is closed, we save the state of the panels to an xml file, using DockManager.SaveLayoutToXml. When the application starts, we load this xml file back with RestoreLayoutFromXml. We do this in the OnLoad, after calling ForceInitialize on DockManager. Normally this works OK, however in the case where an exception has occurred for some reason and the panels are gone, their state isn't serialized into the XML with SaveLayoutToXml and when starting the application after that, the RestoreLayoutFromXml will simply remove the panels and they're no longer visible. Even though the panels were created initially in the InitializeComponent method of the form!

                                    Debugging the code, I see that after RestoreLayoutFromXml, the DockPanel control which normally contains the missing panels has its DockManager set to null. All panels which aren't available anymore also have their DockManager property set to null, as well as their 'Parent' property.

                                    I tried to correct the issue by reparenting the panel controls (which were no longer visible) by first adding the DockPanel control again to the DockManager and adding the missing panels to the DockPanel control's Controls property. However this has no effect, the panels stay hidden.

                                    I have no idea what to do to get them back. What I'm after is really: can I make RestoreLayoutFromXml NOT remove the panels which are created in InitializeComponent but have no data in the xml file? If that's not possible, I'd like to restore the panels to a state which makes them visible again. They're still there, but apparently not visible.

                                    Some code:

                                    [C#]
                                    // in OnLoad // load panelstate if(!CoreStateSingleton.GetInstance().StartedFromVSNet && File.Exists(GuiStateSingleton.GetInstance().PanelStateFilename)) { bool succeeded = false; int numberOfTries = 0; while(!succeeded && (numberOfTries < 10)) { try { _dockingManager.ForceInitialize(); _dockingManager.RestoreLayoutFromXml(GuiStateSingleton.GetInstance().PanelStateFilename); PerformPostDocPanelStateLoadActions(); succeeded = true; } catch(IOException) { Thread.Sleep(300); numberOfTries++; } } }
                                    [C#]
                                    private void PerformPostDocPanelStateLoadActions() { // reset name on feature hints panel. If the user had CTP1/2 installed, it has the wrong title. _featureHintsViewerPanel.Text = "Feature Hints"; // check if the panels are visible. If not, make them visible. This can happen if the panelstate was written after an exception occurred before the panels were created. if(!CoreStateSingleton.GetInstance().StartedFromVSNet) { if(this.panelContainer1.DockManager == null) { _dockingManager.RootPanels.AddRange(new[] { this.panelContainer1}); } if(_commandQueueContentsPanel.Parent == null) { this.panelContainer1.Controls.Add(_commandQueueContentsPanel); } if(_commandQueueContentsPanel.Parent == null) { this.panelContainer1.Controls.Add(_commandQueueContentsPanel); } if(_applicationOutputPanel.Parent == null) { this.panelContainer1.Controls.Add(_applicationOutputPanel); } if(_errorsWarningsPanel.Parent == null) { this.panelContainer1.Controls.Add(_errorsWarningsPanel); } if(_projectExplorerPanel.Parent == null) { this.panelContainer1.Controls.Add(_projectExplorerPanel); } if(_catalogExplorerPanel.Parent == null) { this.panelContainer1.Controls.Add(_catalogExplorerPanel); } if(_featureHintsViewerPanel.Parent == null) { this.panelContainer1.Controls.Add(_featureHintsViewerPanel); } } }
                                    [C#]
                                    // From InitializeComponent. panelContainer1 is a DockPanel instance // // _dockingManager // this._dockingManager.Form = this; this._dockingManager.MenuManager = this._barManager; this._dockingManager.RootPanels.AddRange(new DevExpress.XtraBars.Docking.DockPanel[] { this.panelContainer1, this._projectExplorerPanel, this._catalogExplorerPanel}); this._dockingManager.TopZIndexControls.AddRange(new string[] { "DevExpress.XtraBars.BarDockControl", "DevExpress.XtraBars.StandaloneBarDockControl", "System.Windows.Forms.StatusBar", "System.Windows.Forms.MenuStrip", "System.Windows.Forms.StatusStrip", "DevExpress.XtraBars.Ribbon.RibbonStatusBar", "DevExpress.XtraBars.Ribbon.RibbonControl", "DevExpress.XtraBars.Navigation.OfficeNavigationBar", "DevExpress.XtraBars.Navigation.TileNavPane"}); // // panelContainer1 // this.panelContainer1.ActiveChild = this._errorsWarningsPanel; this.panelContainer1.Controls.Add(this._errorsWarningsPanel); this.panelContainer1.Controls.Add(this._featureHintsViewerPanel); this.panelContainer1.Controls.Add(this._applicationOutputPanel); this.panelContainer1.Controls.Add(this._commandQueueContentsPanel); this.panelContainer1.Dock = DevExpress.XtraBars.Docking.DockingStyle.Bottom; this.panelContainer1.FloatVertical = true; this.panelContainer1.ID = new System.Guid("9940ef3b-0486-4102-8b2d-033379e58e6e"); this.panelContainer1.Location = new System.Drawing.Point(0, 541); this.panelContainer1.Name = "panelContainer1"; this.panelContainer1.OriginalSize = new System.Drawing.Size(200, 200); this.panelContainer1.Size = new System.Drawing.Size(1095, 200); this.panelContainer1.Tabbed = true; this.panelContainer1.Text = "panelContainer1"; // // _errorsWarningsPanel // this._errorsWarningsPanel.Controls.Add(this.controlContainer2); this._errorsWarningsPanel.Dock = DevExpress.XtraBars.Docking.DockingStyle.Fill; this._errorsWarningsPanel.FloatVertical = true; this._errorsWarningsPanel.ID = new System.Guid("9744f701-1275-4853-b00c-cd6481af8dbc"); this._errorsWarningsPanel.Location = new System.Drawing.Point(4, 24); this._errorsWarningsPanel.Name = "_errorsWarningsPanel"; this._errorsWarningsPanel.Options.AllowDockAsTabbedDocument = false; this._errorsWarningsPanel.Options.ShowCloseButton = false; this._errorsWarningsPanel.OriginalSize = new System.Drawing.Size(1087, 146); this._errorsWarningsPanel.Size = new System.Drawing.Size(1087, 145); this._errorsWarningsPanel.Text = "Errors & Warnings"; //
                                • Frans Bouma 10.11.2017

                                  No-one available? I marked this as urgent, no idea why that isn't picked up, we're waiting for an answer so we can proceed with a fix for it and release our own hotfix or not.

                                1 Solution

                                Creation Date Importance Sort by

                                Hello Frans,
                                Thank you for the detailed description.
                                The easiest approach to restore panels in the case of loading a wrong layout is to make a back-up layout and restore it. The idea is simple. Introduce MemoryStream and save DockManager's layout to it using the DockManager.SaveLayoutToStream method before loading your XML. This way, the stream will contain the default layout that is generated in InitializeComponents.
                                Then, try to restore a layout from XML. If the loaded layout is wrong, restore the default layout from the stream. The code may look as follows:

                                [C#]
                                protected override void OnLoad(EventArgs e) { base.OnLoad(e); MemoryStream defaultLayout = new MemoryStream(); _dockingManager.SaveLayoutToStream(defaultLayout); defaultLayout.Seek(0, SeekOrigin.Begin); if (File.Exists(file)) { _dockingManager.ForceInitialize(); _dockingManager.RestoreLayoutFromXml(file); if (IsRestoreFailed()) _dockingManager.RestoreLayoutFromStream(defaultLayout); } }

                                The only thing you need to do is to implement the IsRestoreFailed method. For example, check any panel that is always put into a wrong place after restoring the layout. The following code checks whether dockPanel3 is in a PanelContainer or not.

                                [C#]
                                bool IsRestoreFailed() { return !(dockPanel3.Parent is DockPanel); }

                                Please try it and let me know your result.

                                Nevertheless, the situation with an exception is unclear to me. From what I gather, the exception is thrown during the layout restoration process. It breaks the layout and some panels disappear. I believe you don't need to restore the default layout as suggested above if there are no exceptions. Would you please clarify what kind of exceptions are thrown on restoring? Is it possible to obtain their callstacks as described in the How to obtain the exception's call stack KB article?

                                I look forward to your reply.

                                P.S. We see that you marked this ticket as urgent. I assure you that such tickets have a priority over others which aren't marked as urgent. We process urgent tickets before the others.

                                Show all comments
                                • Frans Bouma 10.11.2017

                                  That's indeed a way around it, didn't think of that, will try it! :)

                                  The exception is unclear to us too: it never happened to us but some clients have reported it, but over the course of a year or two it might be 2-3 times, and they never copied the exception details. To be clear, the exception occurred during our app load/startup, but where exactly that's unclear to us (no further info :( ).

                                  My suspicion is that it might be with us not having_dockingManager.ForceInitialize(); in the OnLoad method (I learned of that method Monday when looking into the issue) and in a rare case it might be the initialization went wrong (as the client who reported this problem to us on Monday reported an exception with a rich text box, which we only use on one of the panels) and left the state of the dockingmanager's panels in an undefined state, leading to the panels not being there, and when our app was closed, the state of only the 2 remaining panels was persisted. Next time the user starts the app, the xml with only data of the 2 panels which were left after the exception the previous run was found and the other panels were automatically hidden/removed by the RestoreLayout method.

                                  What I wondered was: why is RestoreLayoutFromXML and other RestoreLayout methods removing panels which aren't in the xml and there's no way to change that behavior? This is cumbersome in more occasions, e.g. with the button bars, if we want to add a button to a button bar, we can't save/load the layout in the code as users might have the state of an older run and starting the app will remove the button (as it's not in the older xml).

                                  It would be great if the user could state 'RestoreLayout* should load layout info of panels and panels not in the xml should be left as-is' (so they'd still be there if there's no data for them in the xml). that would have solved my problem (and would also make it future proof: we can add panels in newer versions and users can load their state from previous versions. This is important to us as our app is around for a long time now  :)).

                                • Frans Bouma 10.11.2017

                                  The workaround with the initial layout works :) I initially thought it didn't, but we manually add the controls on the panels later, so I first thought it didn't restore everything, but it does.

                                  Still left is the question I had about the removal, so I'll leave the issue open for an answer for that. The initial issue has been resolved for us as in: we can now release an app version which can deal with this issue :)

                                • Nadezhda (DevExpress Support) 10.11.2017

                                  Hello,

                                  >>The exception is unclear to us too: it never happened to us but some clients have reported it, but over the course of a year or two it might be 2-3 times, and they never copied the exception details. To be clear, the exception occurred during our app load/startup, but where exactly that's unclear to us (no further info :( ).
                                  Thank you for the clarification. However, this information is not enough to determine the cause of the behavior. If this exception occurs only on the user side, I suggest you collect the information about this error using the FirstChanceExceptionevent. For more information about this, please refer to the How to obtain the exception's call stack KB article.

                                  >>What I wondered was: why is RestoreLayoutFromXML and other RestoreLayout methods removing panels which aren't in the xml and there's  *no way to change that behavior?
                                  If you wish to show panels that that are not saved in the current layout, you need to register your panels in the LayoutUpgrade event handler. For more information, please review the LayoutUpgrade documentation topic that contains a code snippet illustrating this approach.
                                  Do not hesitate to contact us if you need any further assistance.

                                • Frans Bouma 10.11.2017

                                  I know how to obtain stacktraces and exceptions, thanks ;) I already do that, route the exception to proper dialogs so the user can see it, copy it report it etc. but they didn't copy the data so there's no info in when it happened. I don't expect you to determine what's wrong, that would be impossible ;) I was just mentioning it to give a context when it could happen (as it's not a normal case resulting from normal behavior).

                                  Regarding LayoutUpgrade, that's not going to solve this issue, as the version of the layout on disk (with the missing data) is the same as the one expected. There's just missing data. What I want is telling the dockingmanager to keep the existing elements as-is which aren't in the xml file loaded. So in short:
                                  - form defines the panels on the form, in code. This is executed in InitializeComponent()
                                  - layout is loaded into dockingManager from xml. All elements in that xml which are on the form get their properties updated from the data in the xml, the rest is left as-is (as there's no layout info).
                                  - done.

                                  No migration needed, and it also covers the problem discussed in this thread (and I saw there are other questions related to this elsewhere with XAF where the suggestion was to not save the layout xml if things were missing/different, but that's IMHO also a non-solution, as it doesn't solve the real problem: panels not in the xml are hidden, for no reason (I didn't specify I wanted that behavior, and it's not overridable)

                                • Nadezhda (DevExpress Support) 10.12.2017

                                  Hello Frans,

                                  Let me explain how DockManager restoration works. When you call the RestoreLayout~ method, all panels that were kept in the layout will be recreated. Note that all panels that are located on your form are removed in this case. So, new panels are not shown in your form. So, I suggested you register them in the LayoutUpgrade event handler. Yes, you are right. This event fires only in cases when the DockManager.LayoutVersion property contains another value, then the restored layout. So, you can modify this property before restoring a layout. For example, you can save the current date time in this property.
                                  Please test this approach and let me know if it meets your requirements.

                                • Frans Bouma 10.12.2017

                                  I understand.

                                  Could I make the suggestion to allow the developer to set an option to change the behavior or the restore layout system to do what I suggested?

                                • Nadezhda (DevExpress Support) 10.13.2017

                                  Hello Frans,

                                  Thank you for sharing your ideas with us. We will keep it in mind.
                                  Note that currently, you can get hidden panels in the DockManager.UnregisterDockPanel event handler.