C#中如何动态加载DockPanel

 在WinForm项目中要求实现动态加载DockPanel。

简单研究了下,演示代码如下: 

 1 DockPanel runPanel = dockManager1.AddPanel(DockingStyle.Left);  

 2 runPanel.Name = “Dock1”;  

 3   

 4 DockPanel samePanel = null;  

 5 //查找相同位置是否已有停靠插件  

 6 foreach (DockPanel hasPanel in dockManager1.Panels)  

 7 {  

 8 if (hasPanel.Name != "Dock1" && hasPanel.Dock = = DockingStyle.Left)  

 9 {  

10     samePanel = hasPanel;  

11     break;  

12 }  

13 }  

14   

15 if (samePanel != null)  

16 {  

17     runPanel.DockAsTab(samePanel);  

18 }  

19   

20 runPanel.show();  

 

很简单几行代码,实现了基本意图。看起来问题很快解决。

 

但是实际应用中发现几个问题:

1、当第一次运行时,dockManager1.AddPanel后dockManager1.Panels.Count值为1;当DockAsTab后,dockManager1.Panels.Count值为3,系统居然自动增加了一个DockPanel。

2、使用DockAsTab方式,新的DockPanel总是在已有DockPanel右边生成,然后再融合进去,用户体验非常差,尤其是主程序中间有Mdi子程序时,总会有屏幕不停闪烁的效果。

 

这是怎么回事呢?

 

通过研究DockPanel的相关文档,终于明白DockPanel的运行机制。

 

在论述下面的一些观点前,先说明笔者使用的是DX11版本带的DockManager和DockPanel控件。

 

 

一个典型的DockPanel如下图。它包括DockPanel主体和容器两个部分。DockPanel中要承载其他控件时,控件容器必须建立。

C#中如何动态加载DockPanel

 

 

在DX中,实例化一个DockPanel有三个方法。第一种方法示例如下:

DockPanel runPanel = new DockPanel();

该方法有两点需要注意:

Ø        它不会自动建立控件容器,需要使用者手工添加,代码示例如下:

ControlContainer _dockPanelContainer =newDevExpress.XtraBars.Docking.ControlContainer()

_dockPanelContainer.Name= "dockPanel_Container";

runPanel.Controls.Add(_dockPanelContainer);

//添加控件

runPanel.ControlContainer.Add(newControl());

 

Ø        它需要手工注册到DockManager中去

runPanel.Register(dockManager1);

 

第二种方法是常用的方法,示例如下:

DockPanel runPanel = dockManager1.AddPanel(DockStyle.Left);

它会自动注册DockPanel到DockManager,同时添加一个ControlContainer。

 

第三种方法示例如下:

DockPanel runPanel = sameDockPanel.AddPanel();

它由一个已存在的DockPanel创建一个新的DockPanel。

该新DockPanel的ParentPanel不是创建者,而是由系统自己建立的一个PanelContainer,该PanelContainer同时被设置为RootPanel。

 

停靠模式

DockPanel有两种停靠模式,Split和Tab模式。

 

Split模式界面示例如下图,两个DockPanel根据实际停靠风格并立在一起。

默认情况下,当我们建立好两个DockPanel,将它们直接show出来,它们呈现的就是如下图的Split模式。

C#中如何动态加载DockPanel

 

 

Tab模式如下图,两个DockPanel是以分页样式融合在一起。示例代码如下:

  
using DevExpress.XtraBars.Docking;  

// ...   

//创建一个左停靠控件  

DockPanel panel1 = dockManager1.AddPanel(DockingStyle.Left);  

panel1.Text = "runDockPanel1";  

//由panel1添加一个停靠控件;  

//如果直接把panel1和panel2都show出来,我们可以看到它们是Split模式  

DockPanel panel2 = panel1.AddPanel();  

panel2.Text = " runDockPanel2";  

//将二者的共同父容器设置为Tab模式  

DockPanel container = panel1.ParentPanel;  

container.Tabbed = true;  

 

 

最后演示效果图如下:

C#中如何动态加载DockPanel

 

在这里需要明确的是:

当某个位置(如左边)只有一个DockPanel时,该DockPanel的ParentPanel和RootPanel都是自己。当存在两个及以上DockPanel时,所有DockPanel的ParentPanel和RootPanel都是由系统生成的一个公共DockPanelContainer作为父容器,该容器容纳所有同位置的DockPanel。

 

在关闭同位置的DockPanel时,若只剩下一个DockPanel,则DockPanelContainer会被系统自动释放。

 

明白了上面的这些原理,对解决上面提出的两个问题就找到了答案。

第一个问题如上所述,当同一位置存在两个或两个以上的DockPanel时,系统自动生成一个容器来容纳。

第二个问题,当在使用DockAsTab前,两个DockPanel是Split模式,之后才变为Tab模式。解决方法就是使用已存在的DockPanel建立新的DockPanel,然后把二者的ParentPanel设置为Tab模式。

 

另外在这里提一下,DockPanel中默认只能放置UserControl,如果使用Form类型,需要把TopLevel设置下,但是放置在DockPanel中的Form太有个性了。

 

 

 

一个典型的Tab模式DockPanel如上图。

 

最后,贴出部分实际代码供大家参考:  

  1         /// <summary>  

  2         /// 建立停靠控件t  

  3         /// </summary>  

  4         /// <param name="sCaption">标题</param>  

  5         /// <param name="sName">名称</param>  

  6         /// <param name="ctl">控件实例</param>  

  7         /// <param name="dock">停靠位置?</param>  

  8         /// <param name="dockManager">停靠管理器</param>  

  9         /// <param name="IsNew">是否多次新建窗口</param>  

 10         /// <returns>停靠对象</returns>  

 11         [DisplayName("建立停靠控件")]  

 12         public static DockPanel CreateCtl(string sCaption, string sName, Control ctl, enum_DockLocation dock,  

 13  DockManager dockManager, bool IsNew = false)  

 14         {  

 15             try  

 16             {  

 17                 DockManager runDockManager = dockManager;  

 18                 DockPanel newDockPanel = null;  

 19                 //查找当前列表中是否已有同名的dockpanel  

 20                 DockPanel oldPaneled = null;  

 21   

 22                 runDockManager.BeginUpdate();  

 23   

 24                 //如果是多次新建窗口,则不查找已有Dock  

 25                 if (!IsNew)  

 26                 {  

 27                     oldPaneled = GetHaveDockPanel(runDockManager, sName);  

 28                 }  

 29                

 30   

 31                 if (oldPaneled == null)  

 32                 {  

 33                     DockingStyle dockStyle = DockingStyle.Float;  

 34                     switch (dock)  

 35                     {  

 36                         case enum_DockLocation.Left:  

 37                             dockStyle = DockingStyle.Left;  

 38                             break;                            

 39                         case enum_DockLocation.Buttom:  

 40                             dockStyle = DockingStyle.Bottom;  

 41                             break;  

 42                         case enum_DockLocation.Right:  

 43                             dockStyle = DockingStyle.Right;  

 44                             break;  

 45                         case enum_DockLocation.Center:  

 46                             dockStyle = DockingStyle.Fill;  

 47                             break;  

 48                         default:  

 49                             break;  

 50                     }  

 51   

 52                     DockPanel samePaneled = GetSameDockPanel(runDockManager, dockStyle, sName);  

 53                     if (samePaneled != null)  

 54                     {  

 55                         newDockPanel = samePaneled.AddPanel();  

 56                         newDockPanel.Dock = DockingStyle.Fill;  

 57                     }  

 58                     else  

 59                     {  

 60                         newDockPanel = runDockManager.AddPanel(dockStyle);  

 61                     }  

 62   

 63                     if (newDockPanel != null)  

 64                     {  

 65                         newDockPanel.ID = new System.Guid();  

 66                         newDockPanel.Name = sName;  

 67                         newDockPanel.Text = sCaption;  

 68                         //newDockPanel.Options.ShowAutoHideButton = false;  

 69   

 70                         if (ctl is Form)  

 71                         {  

 72                             Form srcForm = ctl as Form;  

 73                             ctl = ControlLoader.CopyForm2Control(srcForm);  

 74                         }  

 75                         ctl.Dock = DockStyle.Fill;  

 76                         ctl.Visible = true;  

 77                         newDockPanel.Width = ctl.Width;  

 78                         newDockPanel.Height = ctl.Height;  

 79                         newDockPanel.Controls.Add(ctl);  

 80   

 81                         //浮动停靠窗体处理  

 82                         if (newDockPanel.Dock.Equals(DockingStyle.Float))  

 83                         {  

 84                             newDockPanel.FloatForm.Size = ctl.Size;  

 85                             newDockPanel.FloatForm.StartPosition = FormStartPosition.CenterScreen;  

 86                             newDockPanel.FloatForm.AutoSizeMode = AutoSizeMode.GrowOnly;  

 87                             newDockPanel.FloatForm.AutoSize = true;  

 88                         }  

 89   

 90                         newDockPanel.ClosingPanel += new DockPanelCancelEventHandler(ClosingPanel);  

 91                         newDockPanel.ClosedPanel += new DockPanelEventHandler(ClosedPanel);  

 92                     }  

 93                 }  

 94                 else  

 95                 {  

 96                     newDockPanel = samePaneled;  

 97                 }  

 98                 //在DockManager中注册当前插件  

 99                 newDockPanel.Register(runDockManager);  

100   

101                 if (newDockPanel.ParentPanel != null)  

102                 {  

103                     newDockPanel.ParentPanel.Tabbed = true;  

104                 }  

105   

106                 newDockPanel.Visibility = DockVisibility.Visible;  

107                 newDockPanel.Visible = true;  

108   

109                 runDockManager.EndUpdate();  

110   

111                 return newDockPanel;  

112             }  

113             catch (Exception ex)  

114             {  

115                 caCom.XLogErr(ex.Message);  

116                 return null;  

117             }  

118         } 

 

 

 1 在使用DevExpress过程中,原先已经创建好的导航窗体,如何添加到DockPanel中进行展示?

 2 

 3             FormX frmX = new FormX();

 4 

 5             frmX.Show(this.DockPanel1);            

 6 

 7     frmX.Dock = DockStyle.Fill;            

 8 

 9         frmX.TopLevel = false;            

10 

11     frmX.FormBorderStyle = FormBorderStyle.None;            

12 

13     this.DockPanel1.Text = frmX.Text;            

14 

15     this.DockPanel1.TabText = frmX.Text;            

16 

17     this.DockPanel1.Controls.Add(frmX);            

18 

19 这样处理即可,如果DockPanel是动态创建的。需要这样来写:

20 

21 DockPanel panelX = new DockPanel();            

22 

23 panelX = this.DockManager1.AddPanel(DockingStyle.Left);

24 

25 然后将上面的DockPanel1替换成panelX即可。

 

试了以上几种方法还是没有达到效果,看来是我还没研究透

 

你可能感兴趣的:(Panel)