近日在做GridView动态加载模板列的问题是,发现微软的GridView功能竟然如此捉襟见肘。本来想一个AddColumn()即可搞定的问题,到现实中却发现,远非想像中的那般美好。。。。。
于是在网上查了相关的示例,发现都只泛泛讲了一下原理,真正可实用的没有发现,所以一狠心,整理了一下这方面的代码,写了一个派生类。在只使用TextBox模板列的情况下还可以满足要求,至少满足我的要求了。各位可以根据需要扩展即可。本人菜鸟一个,不求甚解,只为实现功能,望高人多多指点。
///
<summary>
/// GridView动态模板列
/// </summary>
/// <example>
/// TemplateFieldEx te = new TemplateFieldEx(150, "动态添加列", "idddd", "id", false);
/// GridView1.Columns.Add(te);
/// </example>
public class TemplateFieldEx : TemplateField
{
/// <summary>
/// 此无参构造必须实现,否则出错
/// </summary>
public TemplateFieldEx()
: base ()
{
}
/// <summary>
/// 构造模板列,具体样式请在GridView中直接设置
/// </summary>
/// <param name="nWidth"> 当前列限定宽度 </param>
/// <param name="strColumnText"> 标题字符串 </param>
/// <param name="strTxtID"> 插入的编辑框ID,注意勿重复 </param>
/// <param name="strField"> 当前弄绑定的字段 </param>
/// <param name="bReadOnly"> 编辑框是否只读 </param>
public TemplateFieldEx( int nWidth, string strColumnText, string strTxtID, string strField, bool bReadOnly):
base ()
{
this .ControlStyle.Width = Unit.Pixel(nWidth);
this .ItemStyle.Width = Unit.Pixel(nWidth);
this .ShowHeader = true ;
this .HeaderTemplate = new GridViewItemTemplate(strColumnText);
this .ItemTemplate = new GridViewItemTemplate(strTxtID, strField, bReadOnly);
}
}
/// <summary>
/// GridView模板项
/// </summary>
public class GridViewItemTemplate : ITemplate
{
private DataControlRowType m_type;
private bool m_bReadOnly;
private string m_strTxtID;
private string m_strColumnText;
private string m_strField;
/// <summary>
/// 此无参构造必须实现,否则出错
/// </summary>
public GridViewItemTemplate() : base ()
{
}
/// <summary>
/// 构造表头列对象
/// </summary>
/// <param name="strColumnText"> 表头字符串 </param>
public GridViewItemTemplate( string strColumnText)
{
m_type = DataControlRowType.Header;
m_strColumnText = strColumnText;
}
/// <summary>
/// 构造元素行对象
/// </summary>
/// <param name="strTxtID"> 当前TextBox控件ID </param>
/// <param name="strField"> 当前TextBox控件绑定的字段 </param>
/// <param name="bReadOnly"> TextBox是否只读 </param>
public GridViewItemTemplate( string strTxtID, string strField, bool bReadOnly)
{
m_type = DataControlRowType.DataRow;
m_strTxtID = strTxtID;
m_strField = strField;
m_bReadOnly = bReadOnly;
}
public void InstantiateIn(System.Web.UI.Control container)
{
switch (m_type)
{
case DataControlRowType.Header:
Literal l = new Literal();
l.Text = m_strColumnText;
container.Controls.Add(l);
break ;
case DataControlRowType.DataRow:
TextBox tb = new TextBox();
/// GridView动态模板列
/// </summary>
/// <example>
/// TemplateFieldEx te = new TemplateFieldEx(150, "动态添加列", "idddd", "id", false);
/// GridView1.Columns.Add(te);
/// </example>
public class TemplateFieldEx : TemplateField
{
/// <summary>
/// 此无参构造必须实现,否则出错
/// </summary>
public TemplateFieldEx()
: base ()
{
}
/// <summary>
/// 构造模板列,具体样式请在GridView中直接设置
/// </summary>
/// <param name="nWidth"> 当前列限定宽度 </param>
/// <param name="strColumnText"> 标题字符串 </param>
/// <param name="strTxtID"> 插入的编辑框ID,注意勿重复 </param>
/// <param name="strField"> 当前弄绑定的字段 </param>
/// <param name="bReadOnly"> 编辑框是否只读 </param>
public TemplateFieldEx( int nWidth, string strColumnText, string strTxtID, string strField, bool bReadOnly):
base ()
{
this .ControlStyle.Width = Unit.Pixel(nWidth);
this .ItemStyle.Width = Unit.Pixel(nWidth);
this .ShowHeader = true ;
this .HeaderTemplate = new GridViewItemTemplate(strColumnText);
this .ItemTemplate = new GridViewItemTemplate(strTxtID, strField, bReadOnly);
}
}
/// <summary>
/// GridView模板项
/// </summary>
public class GridViewItemTemplate : ITemplate
{
private DataControlRowType m_type;
private bool m_bReadOnly;
private string m_strTxtID;
private string m_strColumnText;
private string m_strField;
/// <summary>
/// 此无参构造必须实现,否则出错
/// </summary>
public GridViewItemTemplate() : base ()
{
}
/// <summary>
/// 构造表头列对象
/// </summary>
/// <param name="strColumnText"> 表头字符串 </param>
public GridViewItemTemplate( string strColumnText)
{
m_type = DataControlRowType.Header;
m_strColumnText = strColumnText;
}
/// <summary>
/// 构造元素行对象
/// </summary>
/// <param name="strTxtID"> 当前TextBox控件ID </param>
/// <param name="strField"> 当前TextBox控件绑定的字段 </param>
/// <param name="bReadOnly"> TextBox是否只读 </param>
public GridViewItemTemplate( string strTxtID, string strField, bool bReadOnly)
{
m_type = DataControlRowType.DataRow;
m_strTxtID = strTxtID;
m_strField = strField;
m_bReadOnly = bReadOnly;
}
public void InstantiateIn(System.Web.UI.Control container)
{
switch (m_type)
{
case DataControlRowType.Header:
Literal l = new Literal();
l.Text = m_strColumnText;
container.Controls.Add(l);
break ;
case DataControlRowType.DataRow:
TextBox tb = new TextBox();
tb.ID = m_strTxtID;
tb.Width = Unit.Percentage( 100 );
tb.BorderStyle = BorderStyle.None;
tb.DataBinding += new EventHandler(TextBox_DataBinding);
tb.ReadOnly = m_bReadOnly;
container.Controls.Add(tb);
break ;
default :
break ;
}
}
private void TextBox_DataBinding( object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
GridViewRow gvr = tb.NamingContainer as GridViewRow;
tb.Text = DataBinder.Eval(gvr.DataItem, m_strField).ToString();
}
}
tb.Width = Unit.Percentage( 100 );
tb.BorderStyle = BorderStyle.None;
tb.DataBinding += new EventHandler(TextBox_DataBinding);
tb.ReadOnly = m_bReadOnly;
container.Controls.Add(tb);
break ;
default :
break ;
}
}
private void TextBox_DataBinding( object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
GridViewRow gvr = tb.NamingContainer as GridViewRow;
tb.Text = DataBinder.Eval(gvr.DataItem, m_strField).ToString();
}
}
示例代码如下:
protected
void
Page_Load(
object
sender, EventArgs e)
{
// 注意此处不可放在if(!IsPostBack)中,否则任何一个PostBack命令将会导致此模板列数据丢失,不知何故??
PerformDataBind();
}
private void PerformDataBind()
{
// 注意:此处需要删除列,否则重新添加会导致模板列数量增加
GridView1.Columns.Clear();
TemplateFieldEx te = new TemplateFieldEx( 150 , " 动态添加列 " , " t1 " , " id " , false );
GridView1.Columns.Add(te);
te = new TemplateFieldEx( 150 , " text " , " t2 " , " text " , true );
GridView1.Columns.Add(te);
GridView1.DataSource = CreateDataSource();
GridView1.DataBind();
}
/// <summary>
/// 构造数据源
/// </summary>
/// <returns></returns>
DataTable CreateDataSource()
{
DataTable dt = new DataTable();
DataRow dr;
dt.Columns.Add( new DataColumn( " id " , typeof (Int32)));
dt.Columns.Add( new DataColumn( " text " , typeof ( string )));
for ( int i = 0 ; i < 16 ; i ++ )
{
dr = dt.NewRow();
dr[ 0 ] = i;
dr[ 1 ] = " 列表项目 " + i.ToString();
dt.Rows.Add(dr);
}
return dt;
}
protected void Button1_Click( object sender, EventArgs e)
{
// 读取TextBox控件内容
{
// 注意此处不可放在if(!IsPostBack)中,否则任何一个PostBack命令将会导致此模板列数据丢失,不知何故??
PerformDataBind();
}
private void PerformDataBind()
{
// 注意:此处需要删除列,否则重新添加会导致模板列数量增加
GridView1.Columns.Clear();
TemplateFieldEx te = new TemplateFieldEx( 150 , " 动态添加列 " , " t1 " , " id " , false );
GridView1.Columns.Add(te);
te = new TemplateFieldEx( 150 , " text " , " t2 " , " text " , true );
GridView1.Columns.Add(te);
GridView1.DataSource = CreateDataSource();
GridView1.DataBind();
}
/// <summary>
/// 构造数据源
/// </summary>
/// <returns></returns>
DataTable CreateDataSource()
{
DataTable dt = new DataTable();
DataRow dr;
dt.Columns.Add( new DataColumn( " id " , typeof (Int32)));
dt.Columns.Add( new DataColumn( " text " , typeof ( string )));
for ( int i = 0 ; i < 16 ; i ++ )
{
dr = dt.NewRow();
dr[ 0 ] = i;
dr[ 1 ] = " 列表项目 " + i.ToString();
dt.Rows.Add(dr);
}
return dt;
}
protected void Button1_Click( object sender, EventArgs e)
{
// 读取TextBox控件内容
TextBox t = GridView1.Rows[0].Cells[0].FindControl("t1") as TextBox;
// 如果需要,重新绑定之
PerformDataBinde();
}
// 如果需要,重新绑定之
PerformDataBinde();
}
界面代码如下:
<
form id
=
"
form1
"
runat
=
"
server
"
>
< div >
< asp:GridView ID = " GridView1 " runat = " server " AutoGenerateColumns = " False " >
< HeaderStyle BackColor = " #C0C0FF " />
</ asp:GridView >
< asp:Button ID = " Button1 " runat = " server " OnClick = " Button1_Click " Text = " Button " /></ div >
</ form >
< div >
< asp:GridView ID = " GridView1 " runat = " server " AutoGenerateColumns = " False " >
< HeaderStyle BackColor = " #C0C0FF " />
</ asp:GridView >
< asp:Button ID = " Button1 " runat = " server " OnClick = " Button1_Click " Text = " Button " /></ div >
</ form >