DockPanel

来源:互联网 发布:公知和大v 编辑:程序博客网 时间:2024/05/16 17:46

在使用DockPanel时 需要注意的几个小问题

第一个:

使用过DockPanel的人,都有可能会遇到这样一个错误:

Invalid Content: ActiveContent must be one of the visible contents, or null if there is no visible content.

翻译过来的意思大致是:无效的内容:如果没有一个可见的内容,ActiveContent必须是可见的内容或空。

具体是什么原因,大家可以相互探讨下。下面我说说出现这个问题的几种情况

 代码中的this关键字代表的就是Dockpanel所在的窗体为Form1

1)、当Dockpanel的DocumentStyle不为DockingMdi时,以下代码会出现这个问题      

       Frm_A frmA = null;
       //判断子窗体中是否已经存在在DockPanel中
       foreach (DockContent frm in this.dockPanel1.Contents)
        {
             if (frm is Frm_A)
              {
                    frm.Activate();     //激活子窗体
                    return;
              }
            }

 

            frmA = new Frm_A();
            frmA.MdiParent = this;
            frmA.Show(this.dockPanel1);

        解决方案:看你设置Dockpanel的DocumnetStyle是否为DockingMdi。大家也可以试试其他几种方式(DockingWindow,DockingSdi,SystemMdi)

2)、设置了Dockpanel的DocumentStyle不为DockingMdi时,如果你想要设置窗体Frm_B为左边浮动窗体,需要设置窗体Frm_B的DockAreas为且仅为DockLeft,如果想要实现其他功能可自行去设置其他属性信息,现在请看下面代码

            Frm_B frmB = null;
            //判断子窗体中是否已经存在在DockPanel中
            foreach (DockContent frm in this.dockPanel1.Contents)
            {
                if (frm is Frm_B)
                {
                    frm.Activate();     //激活子窗体
                    return;
                }
            }

            frmB = new Frm_B();
            //frmB.MdiParent = this;
            frmB.Show(this.dockPanel1,DockState.DockLeft);

            注意,如果你在你的代码中加了红色注释的代码,那么程序运行时 也会报上面的那个错

            解决方案:注释红色的代码。

            原因:(个人理解)frmB.Show(this.dockPanel1,DockState.DockLeft);这句代码其实就设置了frmB只停靠在DockPanel左边,此时的frmB是不属于MDI子窗体的,所以一旦你加入红色的代码,程序就会报错。

 

第二个:

拖动、停靠、固定子窗体(显示在Dockpanel中)

拖动:如果你想使你的子窗体可以任意拖动,那么你在设置子窗体的DockAreas属性时,保持默认值,不要修改。

停靠:首先你需设置DockAreas的位置,可以停靠在左、右、下等,也可以通过程序代码控制,参考上面代码。

固定:只需设置你窗体的DockAreas为Document就行了

 

第三个:

子窗体和Contents的判断

很多时候你需要判断Dockpanel中存在多少个子窗体或Contents,请参考下面代码:

foreach(Form in this.MdiChildren)

{

      //这样判断时,停靠的窗体是不会计算在内的

}

 

foreach (DockContent frm in this.dockPanel1.Contents)
 {

     //这样设置后,所有的继承与DockContent的窗体都会被计算在内的

}

 

第四个:

寻找主窗体、动态显示子窗体

参考图:

DockPanel

实现的功能:这里我们需要实现,右键点击A窗体,通过右键菜单来显示窗体B。

  //主窗体的对象
  Form1 form1;

private void showB_Click(object senders, EventArgs e)
 {

           GetFrmMain();  //通过此函数来获取form1     

           foreach (Form frm in form1.MdiChildren)
            {
                if (frm is Frm_B)
                {
                    frm.Activate();
                    return;
                }
            }

            Frm_B frmB = new Frm_B(this);
            frmB.MdiParent = form1;
            frmB.Show(form1.dockPanel1);

}

 

private void GetFrmMain()

{

              if (this.Parent.Parent.Parent.Parent != null)
                {
                    form1 = (Form1)this.Parent.Parent.Parent.Parent;
                }
                else
                {
                    form1 = (Form1)this.Parent.Parent.Parent;
                }

}

 

现在是在A窗体中,this关键字已经代码的不是主窗体了,那么这里我们就需要获取主窗体对象

当A窗体停靠时,需要this.Parent.Parent.Parent.Parent(四个)

不停靠时,只需要三个this.Parent.Parent.Parent

调试代码发现:停靠时

this.Parent 为 {WeifenLuo.WinFormsUI.Docking.DockPane}

this.Parent.Parent 为 {WeifenLuo.WinFormsUI.Docking.DockWindow, BorderStyle: System.Windows.Forms.BorderStyle.None}

this.Parent.Parent.Parent 为 {WeifenLuo.WinFormsUI.Docking.DockPanel, BorderStyle: System.Windows.Forms.BorderStyle.None}

this.Parent.Parent.Parent 为 {TestEvenhandler.Form1, Text: Form1} 就是我们要找的主窗体Form1

 

不停靠时:

this.Parent 为 {WeifenLuo.WinFormsUI.Docking.DockPane}

this.Parent.Parent 为 {WeifenLuo.WinFormsUI.Docking.DockPanel+AutoHideWindowControl, BorderStyle: System.Windows.Forms.BorderStyle.None}

this.Parent.Parent.Parent 为 {TestEvenhandler.Form1, Text: Form1} 就是我们要找的主窗体Form1

 

四个小问题,也算不上技巧,是我在开发中遇到过的,里面的缘由可能解释不是很清楚,忘大家相互探讨,共同进步。

 

 

 

 

 

 

 

DockPanel使用方法

DockPanel有人曰浮动窗体,也就是c#编辑器的样式,如下图:

DockPanel

浮动窗体可以浮动、停靠(上下左右)、分页(如上图的档案录入页面)。

以下记录以下使用方法:

(1)首先找到WeifenLuo.WinFormsUI.Docking.dll,下载WeifenLuo.WinFormsUI.Docking.dll组建(点击下载)。

(2)把该组建添加到引用,创建窗体1为主窗体,窗体2、窗体3为子窗体。把dockpanle工具添加上。

(3)主窗体代码:把dockpanle拖放到主窗体,添加代码 dockPanel1.DocumentStyle = DocumentStyle.DockingMdi;

(4)子窗体:子窗体继承自: WeifenLuo.WinFormsUI.Docking.DockContent ,不是继承自form;定义子窗体对象

form1 f1=new form1();

f1.ShowHint = DockState.Document;
f1.Show(dockPanel1);

显示效果即得到。

     另外也记录下状态,下次打开时候任然保持,用以下方法加载记录状态:

(1)private DeserializeDockContent ddc;

(2)private IDockContent GetContentFromPersistString(string persistString)
        {
          if (persistString == typeof(f1).ToString())
                return f1;
            if (persistString == typeof(f2).ToString())
                return f2;
               else
           {
               return null;
            }
        }

(3)

string configFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "DockPanel.config");
if (File.Exists(configFile))
            dockPanel1.LoadFromXml(configFile, ddc);
            ddc = new DeserializeDockContent(GetContentFromPersistString);

以上方法加载保存的状态,

string configFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "DockPanel.config");
            dockPanel1.SaveAsXml(configFile);

另外,要实现各个dockpanle子窗体之间的互动,例如,vs编辑器中,设计界面的时候,选择一个文本框,属性框中的属性随之改变,使用委托可以解决,可以参看本博客的委托应用1.