动态增加和删除用户控件

系统 1713 0
我们在ASP.NET项目的开发中,需要页面中动态添加和删除多个用户控件。开发环境为Microsoft Visual Studio .NET 2003, 开发语言为C#,并提供源代码下载。

通过一个例子来演示:

我们通过网页来动态创建表和字段时,一次性需要添加多个字段,而字段还有其属性。那么可以通过创建一个用户控件,里面包含多个文本控件或者其他控件来存放一个字段的名称和其多个属性值。然后,在网页中,根据需要创建字段个数的需要,来多次动态加载相等数量的用户控件。

既然能动态加载用户控件,那么加载结束后如果发现某个或几个字段多余,那就需要删除多余的用户控件.在删除时,应该给出提示是否删除。

那么具体操作是:点击"增加"按钮,页面增加一个用户控件,再次点击"增加"按钮又增加一个控件用户。每个用户控件上有一个删除按钮,点击任何用户控件上的“删除”按钮就删除掉该用户控件而不影响其他已存在的用户控件。

我们先提到四个基本概念,他们在动态加载用户控件中需要用到的知识。

什么是用户控件?用户控件就是已经被转换为包含一个或者多个控件的ASP.NET页面. 使用用户控件可以很方便的在多个ASP.NET页面中使用相同的内容和编程逻辑。[1]

什么是PlaceHolder控件?通常不将控件直接添加到页面的Controls集合中。因为我们希望将控件添加到页面的指定的位置。ASP.NET框架中就包含PlaceHolder控件,它用来作为其他控件的容器,我们将控件添加其中,这样我们只需要对PlaceHolder控件定位就可以实现对其他控件的定位。

什么是ViewState?ViewState是.Net中提出的状态保存的一种新途径,它是服务器控件状态保存的基础。通俗的说,就是点击页面的按钮(WebControls.Button类型)提交页面后,页面会被重新加载,那么我们需要保存提交前页面中变量的值,在页面被重新加载后可以使用这些被保存变量的值。在本例中,当我们删除一个控件时,页面会被重新加载,而我们需要删除前用户在其他控件输入的值仍然存在,那么我们就需要ViewState来保存这些值。如果不保存这些值,页面会被重新加载后其他控件输入的值就会被清除,不符合我们的需要。

isPostBack是什么意思?判断页面是否首次被加载,是返回 false, 不是true。通过 isPostBack和ViewState一起就可以在Page_Load中完成页面状态的保存。

完成这个例子的步骤:
(1) 新建一个ASP.NET的项目,(有点废话,但是没有项目是无法完成这个例子的)。创建一个后缀名为aspx的页面,我们需要在它里面来动态添加和删除用户控件(假设该页面的名称为TableDataField.aspx)。创建一个后缀名为ascx的用户控件,(假设该用户控件的名称为WebUserControlCls.ascx),我们需要在它里面添加我们需要的多个服务端控件。呵呵,准备工作完成。

(2) 创建一个字段时,在页面TableDataField.aspx和用户控件WebUserControlCls.ascx包含的内容

<1> 页面TableDataField.aspx包含的内容为:

属性名称 控件类型 用途
WPlaceHolder控件 WebControls.PlaceHolder 作为其他控件的容器
添加按钮 WebControls.Button 点击"增加"按钮,页面增加一个用户控件
获得属性按钮 WebControls.Button 点击"增获得属性"按钮可以获得在用户控件中输入的值
表格 HTML 控件 所有的控件放在这个表格里面,5行3列

<2>用户控件WebUserControlCls.ascx包含的内容为:

属性名称 控件类型 用途
字段的物理名称 WebControls.TextBox 数据库表中的字段名称,一般用英文
字段的逻辑名称 WebControls.TextBox 对用户显示的字段,作为数据库表中的字段名称的别名
字段的属性 WebControls.DropDownList 假设字段属性只允许有两个选择:字符类型和数字类型
字段的长度 WebControls.TextBox 对于字符就是限制长度,是数字就现在其小数位长度
删除按钮 WebControls.Button 点击“删除”按钮就删除掉该用户控件
表格 HTML 控件 所有用户控件放在这个表格里面,1行9列

(3)在页面TableDataField.aspx中,说四个要点。
<1>动态增加用户控件

1、获得用户控件

WebUserControlCls webUserCtrl = (WebUserControlCls)Page.LoadControl("WebUserControlCls.ascx");

2、将用户控件增加到PlaceHolder中

this.plhDataFields.Controls.Add(webUserCtrl);

3、对用户控件的按钮注册动态事件,这里使用事件和代理。关于事件和代理,请参见<<在C#的事件、多播中使用委托>>一文:http://blog.csdn.net/scucj/archive/2006/07/13/915482.aspx

webUserCtrl.btnDelRow.Attributes.Add("onclick", "return confirm('确定要删除该字段吗?');");
webUserCtrl.btnDelRow.Click +=new EventHandler(btnDelRow_Click);

4、对PlaceHolder中的所有用户控件来设置ID属性,将用户控件的ID和被它包含的按钮的ID相同,目的是为了点击用户控件中的"删除"按钮可以通过"删除"按钮ID来获得用户控件ID,然后可以删除该用户控件

setControlsID();

<2>动态删除用户控件

1、创建一个用户控件的实例

WebUserControlCls webUserCtrl = new WebUserControlCls();

2、通过“删除”按钮的ID来获得用户控件的ID

webUserCtrl.ID = btnDel.ID;

3、通过用户控件的ID来删除用户控件

this.plhDataFields.Controls.Remove(this.plhDataFields.FindControl(webUserCtrl.ID));

4、对PlaceHolder中的剩下所有用户控件来重新设置ID属性

setControlsID();

<3>保持用户控件的状态

IsPostBack表示页面是否首次加载,如果是,则用户控件状态个数为0;如果不是,则要加载用户控件。

if ( ! IsPostBack)
... {
// 跟踪用户控件状态个数
ViewState[ " DataFieldCount " ] = 0 ;
}

else
... {
for ( int counter = 0 ;counter < ( int )ViewState[ " DataFieldCount " ];counter ++ )
... {
// 加载用户控件
AddDataField(counter.ToString());
}

}

<4> 用户控件添加成功后,我们提交这个页面。本例通过点击“获得属性”按钮来获得用户控件中输入的值的。
在这其中,我们通过一个foreach来找到所有的webUserCtrl,然后通过webUserCtrl中提供的属性来获得各个控件输入的值。

if (ViewState[ " DataFieldCount " ] != null )
... {
foreach (WebUserControlClswebUserCtrl in this .plhDataFields.Controls)
... {
Response.Write(webUserCtrl.DataFieldName);
Response.Write(webUserCtrl.LogicName);
Response.Write(webUserCtrl.DataFieldType);
Response.Write(webUserCtrl.TypeLength);
Response.Write(
" <br> " );
}

}


(4)在用户控件WebUserControlCls.ascx中,说三个要点。
<1> 应该在其WebUserControlCls.ascx.cs把“删除”按钮的范围从protected改为public,因为我们需要在 页面TableDataField.aspx中对“删除”按钮添加属性和事件。
这样:
protected System.Web.UI.WebControls.Button btnDelRow
应该变为:public System.Web.UI.WebControls.Button btnDelRow
注意,在用户控件WebUserControlCls.ascx移动某个控件时,“删除”按钮的范围会从已经修改的public变回为protected。那么就需要再次将protected改为public。

<2> 在用户控件WebUserControlCls.ascx中为各个控件定义属性,以便页面TableDataField.aspx中可以方便获取控件中输入的值。

比如:

物理名称,只读属性

public string DataFieldName
... {
get
... {
return txtDataFieldName.Text.Trim();
}

}

逻辑名称,只读属性

public string LogicName
... {
get
... {
return txtLogicName.Text.Trim();
}

}

呵呵,整个思路就是这样。由于CSDN的blog不能上传文件,我下面给出 TableDataField.aspx 和 WebUserControlCls.ascx 两个文件的四个部分的源代码。或者给我发邮件: scucj@126.com

<1> TableDataField.aspx

<% ... @Pagelanguage = " c# " Codebehind = " TableDataField.aspx.cs " AutoEventWireup = " false " Inherits = " ScuHR.TableSet.TableDataField " %>
<! DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.0Transitional//EN" >
< HTML >
< HEAD >
< title > TableDataFiled </ title >
< meta name ="GENERATOR" Content ="MicrosoftVisualStudio.NET7.1" >
< meta name ="CODE_LANGUAGE" Content ="C#" >
< meta name ="vs_defaultClientScript" content ="JavaScript" >
< meta name ="vs_targetSchema" content ="http://schemas.microsoft.com/intellisense/ie5" >
</ HEAD >
< body MS_POSITIONING ="GridLayout" >
< form id ="Form1" method ="post" runat ="server" >
< TABLE id ="Table1" style ="Z-INDEX:101;LEFT:56px;WIDTH:680px;POSITION:absolute;TOP:32px;HEIGHT:75px"
cellSpacing
="1" cellPadding ="1" width ="680" border ="1" >
< TR >
< TD style ="WIDTH:21px" >< FONT face ="宋体" ></ FONT ></ TD >
< TD style ="WIDTH:621px" ></ TD >
< TD ></ TD >
</ TR >
< TR >
< TD style ="WIDTH:21px" ></ TD >
< TD style ="WIDTH:621px" >
< asp:PlaceHolder id ="plhDataFields" runat ="server" ></ asp:PlaceHolder ></ TD >
< TD ></ TD >
</ TR >
< TR >
< TD style ="WIDTH:21px" ></ TD >
< TD style ="WIDTH:621px" ></ TD >
< TD ></ TD >
</ TR >
< TR >
< TD style ="WIDTH:21px" ></ TD >
< TD style ="WIDTH:621px" >
< asp:Button id ="btnAadd" runat ="server" Text ="增加" ></ asp:Button ></ TD >
< TD ></ TD >
</ TR >
< TR >
< TD style ="WIDTH:21px" ></ TD >
< TD style ="WIDTH:621px" >< FONT face ="宋体" >
< asp:Button id ="btnGetValue" runat ="server" Text ="获得属性值" ></ asp:Button ></ FONT ></ TD >
< TD ></ TD >
</ TR >
</ TABLE >
</ form >
</ body >
</ HTML >

<2>TableDataField.aspx .cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace ScuHR.TableSet
... {
/**/ /// <summary>
/// TableDataFiled的摘要说明。
/// </summary>
///


public class TableDataField:System.Web.UI.Page
... {
protected System.Web.UI.WebControls.ButtonbtnAadd;
protected System.Web.UI.WebControls.PlaceHolderplhDataFields;
protected System.Web.UI.WebControls.ButtonbtnGetValue;

private void Page_Load( object sender,System.EventArgse)
... {
if ( ! IsPostBack)
... {
// 跟踪用户控件状态值
ViewState[ " DataFieldCount " ] = 0 ;
}

else
... {
for ( int counter = 0 ;counter < ( int )ViewState[ " DataFieldCount " ];counter ++ )
... {
AddDataField(counter.ToString());
}

}

}


Web窗体设计器生成的代码 #region Web窗体设计器生成的代码
override protected void OnInit(EventArgse)
... {
//
// CODEGEN:该调用是ASP.NETWeb窗体设计器所必需的。
//
InitializeComponent();
base .OnInit(e);
}


/**/ /// <summary>
/// 设计器支持所需的方法-不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>

private void InitializeComponent()
... {
this .btnAadd.Click += new System.EventHandler( this .btnAadd_Click);
this .btnGetValue.Click += new System.EventHandler( this .btnGetValue_Click);
this .Load += new System.EventHandler( this .Page_Load);

}

#endregion


private void btnAadd_Click( object sender,System.EventArgse)
... {
ViewState[
" DataFieldCount " ] = ( int )ViewState[ " DataFieldCount " ] + 1 ;
AddDataField(ViewState[
" DataFieldCount " ].ToString());

}


/**/ /// <summary>
/// 通过用户控件来增加动态控件
/// </summary>
/// <paramname="strFieldNum"></param>

http://images.csdn.net/syntaxhighlighting/Outlinin
分享到:
评论

动态增加和删除用户控件


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论