C# 设计时间自定义面板( 拖到里面) 网络自定义控件

分享于 

7分钟阅读

Web开发

  繁體

介绍

当为网站创建长表单时,我经常发现有一些可以扩展或者缩小的窗体有很大的用处。 我创建了一个 baseControl,它可以由Web自定义控件继承,这些控件将允许扩展和缩小功能。 这一切都很完美,但是确实意味着你必须在代码中创建所有的控件。 我不认为这是一个问题,但有些人指出能够将 baseControl 拖到web窗体上,然后将它的他控件转储。 这就是我所做的。

控件基本上是我自己的一个面板版本,我将把它叫做 basePanel。 这个面板有标题栏,其中包含标题。展开或者合同按钮以及关闭按钮。 然后有一个主 DIV 区域,任何控件都可以放置到。 然后有一个页脚,它包含一个取消按钮和一个保存按钮。 所有这些都是通过属性可以控制的,因这里可以使得得到的控件适合一个很好的功能。

以下是一些示例:

示例 1

样例图像

第一个示例显示三个 basePanel 控件。 你可以看到,页眉和页脚部分是灰色的。 我选择不在显示时有关闭按钮,但取消和保存按钮在打开的控件页脚中可以见。

示例 2

样例图像

本示例显示不带页眉或者页脚节的basePanel 控件。 这实际上是继承版本的一个示例,允许我们针对一个业务对象执行多个操作。 在本示例中,控件作为搜索。创建和显示/选择控件。

示例 3

样例图像

这个例子显示了基本的控件,所有的。 你可以看到添加按钮的添加。 在本例中,我将一个按钮控件放到 basePanel 上,以检查事件处理是否处理子控件。

示例 4

样例图像

我已经用红色突出显示了这个控制,因为它非常不显眼。 这实际上与示例 2中的控件相同,但这一次它处于显示/选择模式。 本示例显示多模控件的通用性;每次需要对特定的业务对象执行任何功能。

现在,我将介绍 basePanel的工作原理。 下一次我将解释多模控制。

basePanel

在开始之前,让我来为我的情况辩护。 100%年的测试结果很简单,但是经过三天的寻找,我无法找到如何做到这一点的方法。 不幸的是,VS2005的新帮助功能刚刚安装,现在看来寻找答案是谷歌的唯一领域。 真抱歉 2003的帮助有点帮助。 如果有人知道创建自定义控件的简单方法,即在设计时将其他控件放置到设计时,请让我知道。

创建控件的第一个问题是,我可以将它的他控件放入如何告诉IDE这是允许的控件。 最后,我找到了我所需要的。

[ToolboxData("<{0}:basePanel runat="server">")][Designer("System.Web.UI.Design.ReadWriteControlDesigner, System.Design")]
[PersistChildren(true)]
[ParseChildren(false)]

[ToolboxData] 属性只允许在工具箱中显示,并在拖动到页面时设置默认命名。 真正的工作发生在其他三个属性中。 个人来说,我发现很难获得有关属性标记的内容和它们所做的事情的很难的信息。

因此这些属性解决了在我现有的控件中不能嵌套控件的问题。 下一个问题是,如果呈现控件,所有嵌套控件都出现在 basePanel 之外。 这是由一些相当重要的重写 Render 方法所修复的。

protectedoverridevoid Render(System.Web.UI.HtmlTextWriter writer)
{
 if (HasControls())
 {
 //open a temp stream to render first two//controls into (base control and custome control) System.IO.MemoryStream memstr = new System.IO.MemoryStream();
 System.IO.StreamWriter stream = new System.IO.StreamWriter(memstr);
 HtmlTextWriter wt = new HtmlTextWriter(stream);
 //render first 2 controls to streamfor (int i = 0; i <2; i++)
 {
 this.Controls[i].RenderControl(wt);
 wt.Flush();
 }
 //set to start of stream memstr.Seek(0, System.IO.SeekOrigin.Begin);
 //read back the html from memory System.IO.StreamReader rd = new System.IO.StreamReader(memstr);
 char[] bytes = new char[memstr.Length];
 rd.ReadBlock(bytes, 0, (int)memstr.Length);
 //create string builder of the correct length System.Text.StringBuilder sb = new System.Text.StringBuilder();
 sb.EnsureCapacity((int)memstr.Length);
 //post the bytes to the string builder sb.Append(bytes);
 //close everything memstr.Close();
 stream.Close();
 rd.Close();
 wt.Close();
 //open a temp stream to render any controls added in the IDE memstr = new System.IO.MemoryStream();
 stream = new System.IO.StreamWriter(memstr);
 wt = new HtmlTextWriter(stream);
 //render all other controls added during IDEfor (int i = 2; i < Controls.Count; i++)
 {
 this.Controls[i].RenderControl(wt);
 wt.Flush();
 }
 //set to start of stream memstr.Seek(0, System.IO.SeekOrigin.Begin);
 //read back the html from memory rd = new System.IO.StreamReader(memstr);
 bytes = new char[memstr.Length];
 rd.ReadBlock(bytes, 0, (int)memstr.Length);
 //create string builder of the correct length System.Text.StringBuilder sbChild = new System.Text.StringBuilder();
 sbChild.EnsureCapacity((int)memstr.Length);
 //post the bytes to the string builder sbChild.Append(bytes);
 //close everything memstr.Close();
 stream.Close();
 rd.Close();
 wt.Close();
 //find main div and add all IDE time controls into div statement sb.Replace(" <div class="mainDiv">", 
 " <div class="mainDiv">" + sbChild.ToString());
 //write the html string writer.WriteLine(sb.ToString());
 }
}

可以看到,上面的代码基本上呈现前两个控件( root 控件和自定义面板) 并将它们放在 StringBuilder ( sb ) 中。 然后,它将这些控件之后的所有内容呈现到另一个 StringBuilder ( sbChild ) 中。 然后,在 mainDiv 类上完成一个替代,将所有嵌套控件追加到面板中心。 它不优雅但是它能。

希望自定义控件的其余部分对任何创建自定义控件的人都有意义。 如果你没有和你被卡住,请让我知道。


控制  DES  设计  PAN  拖动  PANE  
相关文章