ASP.NET中动态增加和删除用户控件

翻译|其它|编辑:郝浩|2007-08-30 09:10:05.000|阅读 3098 次

概述:

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>

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

   
通过一个例子来演示:

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

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

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

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

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

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

    什么是  ViewStateViewState  .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 控件

所有的控件放在这个表格里面,53

            

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

属性名称 

控件类型

用途

字段的物理名称

WebControls.TextBox

数据库表中的字段名称,一般用英文

字段的逻辑名称

WebControls.TextBox

对用户显示的字段,作为数据库表中的字段名称的别名

字段的属性

WebControls.DropDownList

假设字段属性只允许有两个选择:字符类型和数字类型

字段的长度

WebControls.TextBox 

 对于字符就是限制长度,是数字就现在其小数位长度

删除按钮 

WebControls.Button 

点击删除按钮就删除掉该用户控件

表格

HTML 控件 

所有用户控件放在这个表格里面,19

                       

    (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(WebUserControlCls webUserCtrl 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

<%...@ Page language="c#" Codebehind="TableDataField.aspx.cs" AutoEventWireup="false" Inherits="ScuHR.TableSet.TableDataField" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
    
<HEAD>
        
<title>TableDataFiled</title>
        
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.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.Button btnAadd;
        
protected System.Web.UI.WebControls.PlaceHolder plhDataFields;
        
protected System.Web.UI.WebControls.Button btnGetValue;
 
        
private void Page_Load(object sender, System.EventArgs e)
        
...{
            
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(EventArgs e)
        
...{
            
//
            // CODEGEN: 
该调用是 ASP.NET Web 窗体设计器所必需的。
            //
            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.EventArgs e)
        
...{
            ViewState[ "DataFieldCount" ] = (
int)ViewState[ "DataFieldCount" ] + 1;
            AddDataField( ViewState[ "DataFieldCount" ].ToString() );
  
        }

        
/**//// <summary>
        
/// 通过用户控件来增加动态控件
        
/// </summary>
        
/// <param name="strFieldNum"></param>
        private void AddDataField(string  strFieldNum) 
        
...
            
//
获得用户控件
            WebUserControlCls webUserCtrl = (WebUserControlCls)Page.LoadControl("WebUserControlCls.ascx");
            
//将用户控件增加到PlaceHolder 
            this.plhDataFields.Controls.Add(webUserCtrl);
            
//对用户控件的按钮注册动态事件
            webUserCtrl.btnDelRow.Attributes.Add("onclick", "return confirm('确定要删除该字段吗?');");
            webUserCtrl.btnDelRow.Click +=
new EventHandler(btnDelRow_Click);
            
//PlaceHolder中的所有用户控件来设置ID属性,目的是为了点击用户控件中的"删除"按钮删除该用户控件
            setControlsID();
        }

        
/**//// <summary>
        
/// 删除所选择的那行用户控件
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>
        private void btnDelRow_Click(object sender, System.EventArgs e)
        
...{
            
//
            ViewState[ "DataFieldCount" ] = (int)ViewState[ "DataFieldCount" ] - 1;
            Button btnDel = (Button)sender;
            WebUserControlCls webUserCtrl = 
new WebUserControlCls();   
            webUserCtrl.ID = btnDel.ID;
            
this.plhDataFields.Controls.Remove(this.plhDataFields.FindControl(webUserCtrl.ID));
            
//
PlaceHolder中的所有用户控件来重新设置ID属性
            setControlsID();

        }
        
        
/**//// <summary>
        
/// 获得所有用户控件中的值
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>
        private void btnGetValue_Click(object sender, System.EventArgs e)
        
...{
            
if(ViewState["DataFieldCount"]!=null
            
...{
                
foreach(WebUserControlCls webUserCtrl in this.plhDataFields.Controls)
                
...{
                    Response.Write(webUserCtrl.DataFieldName);     
                    Response.Write(webUserCtrl.LogicName);
                    Response.Write(webUserCtrl.DataFieldType);
                    Response.Write(webUserCtrl.TypeLength);
                    Response.Write("<br>");
                }    
            }
        }
        
        
/**//// <summary>
        
/// 
PlaceHolder中的所有用户控件来设置ID属性
        
/// </summary>
        private void setControlsID()
        
...{
            
int i=1;
            
//
将用户控件与其按钮设置为相同的ID
            foreach(WebUserControlCls wc in this.plhDataFields.Controls)
            
...{
                wc.ID = i.ToString();
                wc.btnDelRow.ID =i.ToString();
                i++;
            }
   
        }
    }
}

<3>WebUserControlCls.ascx  

<%...@ Control Language="c#" AutoEventWireup="false" codebehind="WebUserControlCls.ascx.cs" Inherits="ScuHR.TableSet.WebUserControlCls" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
<TABLE id="Table1" style="WIDTH: 746px; HEIGHT: 30px" cellSpacing="0" cellPadding="0" width="746"
    border
="1">
    
<TR>
        
<TD>
物理名称:</TD>
        
<TD><FONT face="宋体"><asp:textbox id="txtDataFieldName" runat="server" CssClass="textbox" MaxLength="20" Width="117"
                    Height
="24"></asp:textbox></FONT></TD>
        
<TD><FONT face="宋体">逻辑名称</FONT></TD>
        
<TD style="WIDTH: 119px"><asp:textbox id="txtLogicName" runat="server" CssClass="textbox" MaxLength="20" Width="117px"
                Height
="24px"></asp:textbox></TD>
        
<TD style="WIDTH: 75px"><FONT face="宋体">字段属性:</FONT></TD>
        
<TD style="WIDTH: 87px"><FONT face="宋体"><asp:dropdownlist id="dropDataType" runat="server">
                    
<asp:ListItem Value="0">字符类型</asp:ListItem>
                    
<asp:ListItem Value="1">数字类型</asp:ListItem>
                
</asp:dropdownlist></FONT></TD>
        
<TD><FONT face="宋体">属性长度:</FONT></TD>
        
<TD style="WIDTH: 40px"><FONT face="宋体"><asp:textbox id="txtTypeLength" runat="server" Width="36px" Height="23px">30</asp:textbox></FONT></TD>
        
<TD><FONT face="宋体"><FONT face="宋体"><asp:button id="btnDelRow" Text="删除" runat="server"></asp:button></FONT></FONT></TD>
    
</TR>
</TABLE>

<4>WebUserControlCls.ascx .cs

namespace ScuHR.TableSet
...{
    
using System;
    
using System.Data;
    
using System.Drawing;
    
using System.Web;
    
using System.Web.UI.WebControls;
    
using System.Web.UI.HtmlControls;
    
using System.Text.RegularExpressions; //
使用正则表达式

    
/**//// <summary>
    
///  WebUserControl 的摘要说明。
    
/// </summary>
    public class WebUserControlCls : System.Web.UI.UserControl
    
...{
        
public System.Web.UI.WebControls.Button btnDelRow;//
注意,应该是public
        protected System.Web.UI.WebControls.DropDownList dropDataType;
        
protected System.Web.UI.WebControls.TextBox txtLogicName;
        
protected System.Web.UI.WebControls.TextBox txtDataFieldName;
        
protected System.Web.UI.WebControls.TextBox txtTypeLength;
  

        
private void Page_Load(object sender, System.EventArgs e)
        
...{
            
// 在此处放置用户代码以初始化页面
        }

        
/**//// <summary>
        
/// 物理名称,只读属性
        
/// </summary>
        public string DataFieldName
        
...{
            
get   
            
...{   
                
return   txtDataFieldName.Text.Trim();
            }   
        }

        
/**//// <summary>
        
/// 
逻辑名称,只读属性
        
/// </summary>
        public string LogicName
        
...{
            
get   
            
...{
                
return   txtLogicName.Text.Trim();
            }

        }

        
/**//// <summary>
        
/// 
数据类型,0表示是字符串类型,1表示是数字类型
        
/// </summary>
        public int DataFieldType
        
...{
            
get   
            
...{
                
return   Int32.Parse(dropDataType.SelectedValue);
            }

        }

        
public int TypeLength
        
...{
            
get   
            
...{
                
//
使用正则表达式判断字符串是否为数字
                //
是数字则返回该数字的值
                //
不是则返回-1
                Regex r = new Regex(@"^d+$");
                
if(r.IsMatch(txtTypeLength.Text.Trim()))
                
...{
                    
return   Int32.Parse(txtTypeLength.Text);
                }
                
else
                
...{
                    
return -1;
                }    
            }
        }

        
Web 窗体设计器生成的代码#region Web 窗体设计器生成的代码
        
override protected void OnInit(EventArgs e)
        
...{
            
//
            // CODEGEN: 
该调用是 ASP.NET Web 窗体设计器所必需的。
            //
            InitializeComponent();
            
base.OnInit(e);
        }
  
        
/**//// <summary>
        
///  设计器支持所需的方法 - 不要使用代码编辑器
        
///  修改此方法的内容。
        
/// </summary>
        private void InitializeComponent()
        
...{
            
this.Load += new System.EventHandler(this.Page_Load);

        }
        
#endregion

    }
}


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com

文章转载自:csdn

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP