天天看点

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

转http://blog.csdn.net/yuanfang8789/archive/2007/08/17/1748554.aspx

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

        // 如果需要,重新绑定之

           PerformDataBind();

    }

界面代码如下:

    <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>