GridView动态添加模板列,并解决数据列PostBack后数据丢失问题!

近日在做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();
                     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();
        }
    }

示例代码如下:

 

 

     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控件内容
        TextBox t = GridView1.Rows[0].Cells[0].FindControl("t1") as TextBox;
        
//  如果需要,重新绑定之
        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 >

你可能感兴趣的:(GridView)