• 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中要承载其他控件时,控件容器必须建立。

    在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模式。

    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;  

    最后演示效果图如下:

    在这里需要明确的是:

    当某个位置(如左边)只有一个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即可。

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

  • 相关阅读:
    Python 之 raw_input()与input()区别
    Python基础语法
    在Cloudera Hadoop CDH上安装R及RHadoop(rhdfs、rmr2、rhbase、RHive)
    MapReduce 过程详解
    Cloudera Manager and CDH安装及配置
    RFC 目录
    聊一聊 tcp拥塞控制 九 fack
    聊一聊tcp 拥塞控制 八 相关数据结构&& 概念
    聊一聊 tcp 拥塞控制 七 转载
    udp connected socket
  • 原文地址:https://www.cnblogs.com/endv/p/4587932.html
Copyright © 2020-2023  润新知