Динамические элементы управления — несколько элементов управления с одинаковым идентификатором

У меня проблема с моей динамически созданной таблицей/элементами управления. Я искал в Интернете, чтобы найти некоторые решения, и попробовал несколько, но по какой-то причине я не вижу кода ниже.

По сути, я хочу иметь возможность добавлять новые столбцы при необходимости, а затем перезагружать таблицу, а также удалять динамически созданный столбец. Затем я хотел бы выполнить обратную передачу, чтобы получить значения ячеек, которые были созданы динамически. Довольно просто.

Вот код:

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

person Todd    schedule 29.08.2009    source источник
comment
Моя проблема решена. У меня была asp:table на моей странице ASPX и не было заполнителя. Я удалил asp:table и заменил его заполнителем и очищал элементы управления каждый раз, когда я генерирую таблицу. Теперь работает идеально. Спасибо за помощь.   -  person Todd    schedule 30.08.2009
comment
Я говорил в ближайшее время. Я прокомментировал назначение идентификатора из текстовых полей, поэтому, когда я удалил его, он по-прежнему выдает ту же ошибку.   -  person Todd    schedule 30.08.2009
comment
Решил. В итоге возникла проблема с именованием идентификаторов текстовых полей. Спасибо за звуковую панель, ребята.   -  person Todd    schedule 30.08.2009


Ответы (3)


Почему бы просто не использовать сетку данных с шаблонными столбцами для ваших кнопок и автоматически генерировать столбцы, для которых установлено значение true, а затем динамически добавлять столбцы в таблицу данных, к которой вы привязываетесь. Затем вы можете использовать onItemCommand для обратной передачи, получить выбранный индекс и использовать findcontrol, чтобы найти новый элемент управления и его значение.

Брайан

person Bernesto    schedule 29.08.2009
comment
Это настраиваемый макет таблицы, который я не могу создать с помощью сетки данных или сетки. - person Todd; 30.08.2009
comment
@chopps: я думаю, вы можете создать практически любой макет с помощью HTML и CSS. По крайней мере, я бы использовал существующие элементы управления, такие как элемент управления повторителем, вместо того, чтобы создавать таблицы вручную. - person Juri; 30.08.2009

Как я уже упоминал в своем комментарии, я думаю, вы сможете добиться того, что вам нужно, с помощью существующих элементов управления .Net (и CSS, шаблонов и соответствующего HTML-кода).

В противном случае для вашей проблемы с идентификатором сгенерированных элементов управления вы можете создать дополнительный класс - назовите его UniqueId или что-то в этом роде - где у вас есть общедоступный метод GetUniqueId(string). Класс UniqueId запоминает все идентификаторы, которые должны быть переданы, и записывает их в список или каким-либо образом.

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
}

Такой метод должен обеспечивать получение уникального идентификатора. Вы также можете попробовать создать тест большой таблицы в событии OnInit вашей страницы. Элементы управления обычно всегда следует добавлять в коллекцию элементов управления на этом этапе жизненного цикла.

person Juri    schedule 29.08.2009

У нас была такая же проблема на работе. Что я сделал, чтобы решить эту проблему, так это установить radGrid.MasterTableView.EnableColumnsViewState = false

Причина в том, что RadGrid воссоздавался после PostBack из-за динамических элементов управления и имел ViewState, который также пытался добавить столбцы. Затем столбцы были «удвоены», поэтому возникла ошибка «Несколько элементов управления с одним и тем же идентификатором».

person Patrick McElreavy    schedule 10.11.2010