views:

783

answers:

2

Hey Everyone,

I am having a problem with my dynamically created table/controls. I've searched the interwebs to find some solutions and tried a few but for what ever reason im not seeing it the code below.

Essentially I want to be able to add new columns when needed and then reload the table as well as removing a column that was dynamically created. I would then like to do a postback to get the values of the cells that where dynamically created. Fairly straight forward.

Here is the code:

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Text;

namespace TimeTracker
{
    public partial class _Default : System.Web.UI.Page
    {


        private int NumberofRows
        {
            get
            {
                object o = ViewState["NumberofRows"];
                if (o == null) return 4;
                return (int)o;
            }
            set
            {
                ViewState["NumberofRows"] = value;
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            //if (!Page.IsPostBack)
            //{
                CreateBigTestTable();
            //}
        }

        /// <summary>
        /// 
        /// </summary>
        protected void CreateBigTestTable()
        {
            Table1.Controls.Clear();
            DataTable dt;

            if (Cache["GetData"] != null)
            {
                dt = (DataTable)Cache["GetData"];
            }
            else
            {
                dt = GetData();
                Cache.Insert("GetData", dt, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(20));
            }

            int colSpan = dt.Rows.Count;
            int rowCount = NumberofRows;

            // Create a TableHeaderRow.
            TableHeaderRow headerRow = new TableHeaderRow();
            headerRow.BackColor = System.Drawing.Color.AliceBlue;

            // Create TableCell objects to contain the text for the header.
            TableHeaderCell headerTableCell1 = new TableHeaderCell();
            TableHeaderCell headerTableCell2 = new TableHeaderCell();
            TableHeaderCell headerTableCell3 = new TableHeaderCell();
            headerTableCell1.Text = "";
            headerTableCell1.Scope = TableHeaderScope.Column;
            headerTableCell1.AbbreviatedText = "";

            Label lblheaderTableCell2 = new Label();
            lblheaderTableCell2.Text = "Labor Category Hours";

            ImageButton imgBtnNew = new ImageButton();
            imgBtnNew.ImageUrl = "~/images/plus.gif";
            imgBtnNew.ImageAlign = ImageAlign.Top;
            imgBtnNew.ID = "imgBtnNew";
            imgBtnNew.Click += new ImageClickEventHandler(imgBtnNew_Click);

            headerTableCell2.Controls.Add(lblheaderTableCell2);
            headerTableCell2.Controls.Add(imgBtnNew);
            headerTableCell2.ColumnSpan = colSpan;

            headerTableCell3.Text = "Total Hours";
            headerTableCell3.HorizontalAlign = HorizontalAlign.Right;
            headerTableCell3.Scope = TableHeaderScope.Column;
            headerTableCell3.AbbreviatedText = "Total Hours";
            headerTableCell3.ColumnSpan = 2;

            headerRow.Cells.Add(headerTableCell1);
            headerRow.Cells.Add(headerTableCell2);
            headerRow.Cells.Add(headerTableCell3);

            ///
            ///Sub header row
            ///
            TableHeaderRow headerRow1 = new TableHeaderRow();
            headerRow1.BackColor = System.Drawing.Color.AliceBlue;

            TableHeaderCell headerTableCell11 = new TableHeaderCell();
            TableHeaderCell headerTableCell22 = new TableHeaderCell();
            TableHeaderCell headerTableCell33 = new TableHeaderCell();
            TableHeaderCell headerTableCell44 = new TableHeaderCell();

            headerTableCell11.Text = "Functional Area";
            headerTableCell11.Scope = TableHeaderScope.Column;
            headerTableCell11.AbbreviatedText = "Functional Area";
            headerTableCell11.Height = 100;
            headerTableCell11.VerticalAlign = VerticalAlign.Bottom;

            headerRow1.Cells.Add(headerTableCell11);

            // Labor Category Title
            foreach (DataRow dr in dt.Rows)
            {
                TableCell tempCell = new TableCell();

                Label lblLaborCategoryTitle = new Label();
                lblLaborCategoryTitle.Text = dr["Title"].ToString();
                tempCell.Controls.Add(lblLaborCategoryTitle);

                ImageButton ctrl = new ImageButton();
                ctrl.ID = "dynamicImageButton" + dr["ID"].ToString();
                ctrl.ImageUrl = "~/images/delete.gif";
                ctrl.Click += new ImageClickEventHandler(img_Click);

                tempCell.Controls.Add(ctrl);

                headerRow1.Cells.Add(tempCell);  
            }

            headerTableCell33.Text = "Current Period";
            headerTableCell33.HorizontalAlign = HorizontalAlign.Right;
            headerTableCell33.Scope = TableHeaderScope.Column;
            headerTableCell33.AbbreviatedText = "Current Period";
            headerTableCell33.Height = 100;
            headerTableCell33.VerticalAlign = VerticalAlign.Top;
            headerRow1.Cells.Add(headerTableCell33);

            headerTableCell44.Text = "Cummulative";
            headerTableCell44.HorizontalAlign = HorizontalAlign.Right;
            headerTableCell44.Scope = TableHeaderScope.Column;
            headerTableCell44.AbbreviatedText = "Cummulative";
            headerTableCell44.Height = 100;
            headerTableCell44.VerticalAlign = VerticalAlign.Top;
            headerRow1.Cells.Add(headerTableCell44);

            // Add the TableHeaderRow as the first item in the Rows collection of the table.
            Table1.Rows.AddAt(0, headerRow);
            Table1.Rows.AddAt(1, headerRow1);

            ///
            /// Add rows to the table.
            ///
            for (int rowNum = 0; rowNum < rowCount; rowNum++)
            {
                TableRow tempRow = new TableRow();

                // add cell for functional area
                TableCell tempCellSpacer = new TableCell();
                tempCellSpacer.Text = "Functional Area: " + rowNum.ToString();
                tempRow.Cells.Add(tempCellSpacer);

                for (int cellNum = 0; cellNum < colSpan; cellNum++)
                {
                    TableCell tempCell = new TableCell();

                    TextBox tb = new TextBox();
                    tb.MaxLength = 128;
                    //tb.ID = "txt_Number" + cellNum.ToString();
                    tb.Text = String.Format("({0},{1})", rowNum, cellNum);
                    tempCell.Controls.Add(tb);
                    tempRow.Cells.Add(tempCell);
                }

                // add cells for current period
                TableCell tempCurrentPeriod = new TableCell();
                tempRow.Cells.Add(tempCurrentPeriod);

                // add cells for Cummulative
                TableCell tempCummulative = new TableCell();
                tempRow.Cells.Add(tempCummulative);

                Table1.Rows.Add(tempRow);
            }

            ///
            /// Create a TableFooterRow
            /// 
            TableFooterRow footerRow = new TableFooterRow();
            footerRow.BackColor = System.Drawing.Color.AliceBlue;

            // Create TableCell objects to contain the text for the footer.
            TableCell footerTableCell1 = new TableCell();
            TableCell footerTableCell2 = new TableCell();
            TableCell footerTableCell3 = new TableCell();
            footerTableCell1.Text = "Total Amount";
            footerTableCell1.ColumnSpan = colSpan+1;
            footerTableCell1.HorizontalAlign = HorizontalAlign.Right;
            footerTableCell2.Text = "Column 2 footer";
            footerTableCell2.HorizontalAlign = HorizontalAlign.Right;
            footerTableCell3.Text = "Column 3 footer";
            footerTableCell3.HorizontalAlign = HorizontalAlign.Right;

            // Add the TableCell objects to the Cells collection of the TableFooterRow.
            footerRow.Cells.Add(footerTableCell1);
            footerRow.Cells.Add(footerTableCell2);
            footerRow.Cells.Add(footerTableCell3);

            // Add the TableFooterRow to the Rows collection of the table.
            Table1.Rows.Add(footerRow);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void img_Click(object sender, ImageClickEventArgs e)
        {
            Response.Write("Test");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void imgBtnNew_Click(object sender, ImageClickEventArgs e)
        {
            DataTable dt;

            if (Cache["GetData"] != null)
            {
                dt = (DataTable)Cache["GetData"];
                dt.Rows.Add(new Object[] { 5, "Test" });
            }
            else
            {
                dt = GetData();
                dt.Rows.Add(new Object[] { 5, "Test" });
                Cache.Insert("GetData", dt, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(20));
            }

            CreateBigTestTable();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnUpdate_Click(object sender, EventArgs e)
        {
            ProcessControls(Table1);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="control"></param>
        private void ProcessControls(Control control)
        {
            foreach (Control ctrl in control.Controls)
            {
                if (ctrl.GetType() == typeof(TextBox))
                {
                    Response.Write(string.Format("Control ID: {0} Text: {1}<br/>", ((TextBox)ctrl).ID, ((TextBox)ctrl).Text)); 
                }

                if (ctrl.HasControls())
                    ProcessControls(ctrl);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private DataTable GetData()
        {
            DataTable dt = new DataTable();
            DataRow dr;
            dt.Columns.Add(new System.Data.DataColumn("ID", typeof(String)));
            dt.Columns.Add(new System.Data.DataColumn("Title", typeof(String)));

            dr = dt.NewRow();
            dr[0] = "1";
            dr[1] = "Web Developer";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = "2";
            dr[1] = "Project Manager";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = "3";
            dr[1] = "System Analyst";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = "4";
            dr[1] = "Database Administrator";
            dt.Rows.Add(dr);

            return dt;
        }
    }
}
+1  A: 

Why not just use a datagrid with templated columns for your buttons and autogenerate columns set to true, then dynamically add columns the the datatable you are binding to. You can then use onItemCommand for your postback, get the selected index and the use findcontrol to find the new control and it's value.

Brian

Bernesto
It's a custom table layout that I can't create with a datagrid or gridview.
chopps
@chopps: I guess you could create pretty much any layout with HTML and CSS. At least I would use existing controls like the repeater control instead of creating the tables manually.
Juri
A: 

As I mentioned in my comment I guess you should be able to achieve what you need with existing .Net controls (and CSS, templates and appropriate HTML code).

Otherwise for your ID problem of generated controls you could create an extra class - call it UniqueId or something - where you have a public method GetUniqueId(string). The UniqueId class remembers all the id's that have to be passed and records them in a list or somehow.

public string GetUniqueId(string key)
{
  //lookup "key" in a private list
  //if the key is present, generate a random number, append it
  //to "key", add it to the list for remembering it and return it
}

Such a method should ensure to always get a unique id. What you could also try is to create your big table test in the OnInit event of your page. Controls should usually always be added to the controls collection in that phase of the life-cycle.

Juri