Nevron Forum

Reliably finding controls in the nDockManager? Proper way to find & remove controls?

https://www.nevron.com/Forum/Topic4496.aspx

By lars knox - Thursday, November 18, 2010

Hi,

I'm trying to use the NDockManager in a specific way and I'm running into some difficulty. My requirements are that various User Defined Controls should be able to be added and removed from the NDockManager when a user clicks a button or selects a menu item. I have a code base that works for the most part except when I get the following error: "Unable to cast object of type 'Nevron.UI.WinForm.Docking.l1lIlll' to type 'Nevron.UI.WinForm.Docking.NDockingPanelHost'."

Could you please explain what exactly is the type: 'Nevron.UI.WinForm.Docking.l1lIlll' ? Why the funny string of | (bars), I (capital I's), and 1 (ones) ? What does this represent?

However, my main issue is that I cannot reliable find and remove a control (and its panel & panelHost) if a user has been moving and re-docking panelHosts. Perhaps I am using a bad approach. Any suggestions would be extremely welcome. Thanks!!

This is how I'm adding controls to the NDockManager:

private void AddControl(string text, string key, Control control, DockStyle dockStyle)
{
 // === The control. This is a user defined control that we have written.
 control.Tag                             = key;
 control.Dock                            = DockStyle.Fill;

 // === The panel.
 NDockingPanel panel                     = new NDockingPanel();
 panel.Key                               = key;
 panel.Text                              = text;           
 panel.Dock                              = dockStyle;
 panel.Closing                           += new PanelCancelEventHandler(_panel_Closing);
 panel.Controls.Add(control);

 // === The panel host.
 NDockingPanelHost panelHost             = new NDockingPanelHost();
 panelHost.AddChild(panel);

 // === The dock manager.
 nDockManager1.RootContainer.RootZone.AddChild(panelHost, nDockManager1.RootContainer.RootZone.Children.Count);
}


Example of trying to remove a control from the dock manager:


private bool removeControlFromWhereEverItIs(string key)
{
 Control controlToRemove             = null;
 NDockingPanel panelToRemove         = null;
 NDockingPanelHost panelHostToRemove = null;
 bool foundTheControl                = _removeControlFromWhereEverItIs(key, null, ref panelHostToRemove, ref panelToRemove, ref controlToRemove);

 if (foundTheControl)
 {
  if (controlToRemove != null) // We have to remove the control OUTSIDE of the iterating over the panel.Controls collection.
   panelToRemove.Controls.Remove(controlToRemove);

  if (panelToRemove != null) // We need to remove its panel also.
   panelHostToRemove.RemoveChild(panelToRemove);

  if (panelHostToRemove != null) // We need to remove its panel also.
   nDockManager1.RootContainer.RootZone.RemoveChild(panelHostToRemove);
 }

 return foundTheControl;
}
private bool _removeControlFromWhereEverItIs(string key, INDockZoneChild recursiveCanBeNullForTopLevel, ref NDockingPanelHost panelHostToRemove, ref NDockingPanel panelToRemove, ref Control controlToRemove)
{
 bool foundTheControl                    = false;

 if (recursiveCanBeNullForTopLevel == null)
 {
  foreach (INDockZoneChild ph in nDockManager1.RootContainer.RootZone.Children)
   if (!foundTheControl)
    foundTheControl = _removeControlFromWhateverZoneItsIn(key, ph, ref panelHostToRemove, ref panelToRemove, ref controlToRemove);
   else
    break;
 }
 else
 {
  NDockingPanelHost prototype         = new NDockingPanelHost();
  NDockingPanelHost panelHost         = (NDockingPanelHost)recursiveCanBeNullForTopLevel; // <<--== ERROR OCCURS HERE: 'Nevron.UI.WinForm.Docking.l1lIlll' to type 'Nevron.UI.WinForm.Docking.NDockingPanelHost'

  foreach (NDockingPanel panel in panelHost.Children)
  {
   foreach (Control control in panel.Controls)
   {
    if (control.Tag.ToString() == key)
    {
     controlToRemove         = control;
     panelToRemove           = panel;
     panelHostToRemove       = panelHost;
     foundTheControl         = true;
     break;
    }
   }
   if (foundTheControl) break;
  }
 }

 return foundTheControl;
}

By Nevron Support - Thursday, November 18, 2010

Hi Lars,

These bars, capital I and ones represents obfuscated classes, methods or properties that are private or internal.

When you add NDockingPanels into NDockManager and then on runtime change their position in the docking framework, their parents can be changed internally and the initial structure may be different.

For example according the way you add a panel and panel host, after you add then the RootZone should have 2 children - one that hosts the NUIDocuments (added internally) and the host that you add.

If you add another panel in new host your RootZone should have 3 children, but if you drag the new panel to be in the same host as the first one the second host will be removed from the docking structure internally.

To remove a control that is somewhere in the panels you can iterate through the NDockManager.Panels collection to find the control. To remove this panel from the docking framework you should set NDockManager.DisposePanelsOnClose property to true, call NDockManager.UnregisterDockPanel method and close the panel by calling its Close method.

Here is one example method that you can use to do the task:

nDockManager1.DisposePanelsOnClose = true;

...

private bool RemoveControl(string key)
{
    int nCount_i = nDockManager1.Panels.Length;
    for (int i = 0; i < nCount_i; i++)
    {
        NDockingPanel panel = nDockManager1.Panels[i] as NDockingPanel;
        if(panel == null)
            continue;
        int nCount_j = panel.Controls.Count;
        for (int j = 0; j < nCount_j; j++)
        {
            Control c = panel.Controls[j];
            if (c.Tag != null)
            {
                if (c.Tag.ToString() == key)
                {
                    panel.Controls.Remove(c);
                    nDockManager1.UnregisterDockPanel(panel);
                    panel.Close();
                    return true;
                }
            }
        }
    }

    return false;
}

To remove the panel host from the docking framework, first you should check whether this panel host doesn't hosts any other panels or nested hosts.

I hope this helps.

 

 

By lars knox - Thursday, November 18, 2010

Thank you very much for your reply! I am trying to implement your suggestion now. However, I notice that the nDockManager1 (type Nevron.UI.WinForm.Docking.NDockManager) does not have the property DisposePanelsOnClose.

I have searched the namespace with VisualStudio's Object Browser and cannot locate the property anywhere. The version of Nevron.UI.WinForm.Docking that I am using is 8.10.15.12

By Nevron Support - Friday, November 19, 2010

Hi Lars,

This property was added in newer version, that's why you can't find it.

The purpose of this property is if you create new panels intensively on runtime and then close them the memory footprint increases because when you close these panels they still exist in the memory. If this property is set to true after you close a panel it becomes disposed.

By lars knox - Friday, November 19, 2010

Can I emulate setting the DisposePanelsOnClose property by just Disposing the panels after I Close them? Or do I have to worry about a memory leak in the application as users open and close panels with the version of Nevron we are currently using?

Thanks, by the way, your previous solution works very well. I am only concerned with the potential of a memory leak right now.

By Nevron Support - Tuesday, November 23, 2010

Hi Lars,

You can call panel.Dispose() method after panel.Close().

This should do the job.

By lars knox - Tuesday, November 23, 2010

Can I emulate setting the DisposePanelsOnClose property by just Disposing the panels after I Close them? Or do I have to worry about a memory leak in the application as users open and close panels with the version of Nevron we are currently using?

I just wanted to ask this question again. Any ideas? Thanks
By Nevron Support - Wednesday, November 24, 2010

Hi Lars,

Disposing the panels after you close them will avoid memory leak.