九、以编程方式添加 ASP.NET 控件
有时,在运行时创建控件比在设计时创建控件更可行。例如,假定有一个搜索结果页,您要在其中将以表的形式显示结果。由于不知道要返回多少项,因此您需要每个返回的项动态生成一个表行。
说明: 现有控件通常可以提供从动态创建控件中获得的功能。例如,Repeater、DataList 和 RadioButtonList 控件可以在页运行时动态创建行或其他控件元素。
要通过编程向页添加控件,则必须有放置新控件的容器。例如,如果您打算创建表行,那么容器就是表。如果没有明显的控件用作容器,可以使用 PlaceHolder 或 Panel Web 服务器控件。
在某些情况下,可能需要既创建静态文本又创建控件。要创建静态文本,可以使用 Literal 或 Label Web 服务器控件。然后可以将这些控件像其他控件一样添加到容器中。
通过编程方式将控件添加到 Web 网页
1、创建控件的实例并设置其属性,如下面的示例所示:
Label myLabel = new Label();
myLabel.Text = "Sample Label";
说明: 控件通常在页的初始化阶段添加到页中
2、将新控件添加到页上已有容器的 Controls 集合中,如下面的示例所示:
Panel Panel1= new Panel();
Panel1.Controls.Add(myLabel);
说明: 因为 Controls 属性是一个集合,您可以使用 AddAt 方法在特定位置放置新控件,例如在其他控件的前面。但是这将会在页中引入错误。
下面的代码示例演示名为 DropDownList1 的控件的 SelectedIndexChanged 事件的事件处理程序。该处理程序创建的标签 (Label) 控件的数量和用户从下拉列表中所选的数量相同。这些控件的容器是名为 Placeholder1 的 PlaceHolder Web 服务器控件。
private void DropDownList1_SelectedIndexChanged(object sender, System.EventArgs e)
{
DropDownList DropDownList1 = new DropDownList();
PlaceHolder PlaceHolder1 = new PlaceHolder();
// Get the number of labels to create.
int numlabels = System.Convert.ToInt32(DropDownList1.SelectedItem.Text);
for (int i=1; i<=numlabels; i++)
{
Label myLabel = new Label();
// Set the label's Text and ID properties.
myLabel.Text = "Label" + i.ToString();
myLabel.ID = "Label" + i.ToString();
PlaceHolder1.Controls.Add(myLabel);
// Add a spacer in the form of an HTML <br /> element.
PlaceHolder1.Controls.Add(new LiteralControl("<br />"));
}
}
安全说明: 网页中的用户输入可能包括潜在有害的客户端脚本。默认情况下,ASP.NET 网页验证用户输入是否不包括脚本或 HTML 元素。
3、动态 Web 服务器控件和视图状态
在运行时动态创建 Web 服务器控件时,有关控件的某些信息存储在随页一起呈现的视图状态中。但在将页回发到服务器时,需要先在页的 Init 事件中实例化非动态控件(在页上定义的控件)并加载视图状态信息,然后才能重新创建动态控件(通常在 Page_Load 处理程序中)。因此在动态控件创建之前,视图状态将暂时不与页的控件同步。余下的视图状态信息在 Page_Load 事件运行之后、控件事件处理方法调用之前加载到动态创建的控件中。
多数情况下,此视图状态处理模型都可以很好地工作。通常您将动态控件添加到容器的控件集合的末尾。因此,为动态控件存储的视图状态信息成为相应容器的视图状态结构末端的附加信息,并且页可以在控件创建之前忽略它。
但是,动态创建的控件的视图状态信息将在两种情况下会出问题:
·如果您在现有控件之间插入动态控件。
·如果您动态插入控件,并随后在往返期间使用不同的值重新插入它们。
如果在现有控件之间插入动态控件,该动态控件的视图状态信息将插入到视图状态结构的相应位置。在发送页并加载视图状态时,动态控件还不存在;因此,视图状态中的附加信息将不会对应于正确的控件。结果通常是出现表明存在无效强制转换的错误。
如果您在每次往返期间重新插入,则每次动态创建的控件都将从上述控件集的视图状态中选取属性值。在很多情况下,可以通过将容器控件的 EnableViewState 属性设置为 false 来避免此问题。在本例中,将不会保存有关动态控件的任何信息,并且与后续版本的控件之间不存在任何冲突。