How to dynamically generate controls including UserControls? Same as adding windows controls:
STEP 1: Add
STEP 2: Draw/Redraw
STEP 3: Read
STEP 1: Add
STEP 2: Draw/Redraw
STEP 3: Read
Let’s say we have DataTable having following data in it:
ID CAPTION DATATYPE
1 Name Text2 Sports List
3 Date Date
The UserControl contains a TextBox for date string, ImageButton showing a Calendar image; and a Calendar control itself shown/hide when the Calendar image is clicked, see fig1.
FIG1: UCtlCalendar user control.
Note that events are mapped and are working for dynamically generated UserControl.
Following is the output(fig2) that is desired; TextBox controls, a ListBox, and a UserControl.
FIG2: Desired output with dynamic controls.
Following illustration (fig3) the Calendar control upon click event.
FIG3: WebUserControl click event
Let’s follow same 4 stepped procedure.
STEP 1: Add a PlaceHolder control called phControls
STEP 2: Draw dynamic controls
STEP 3: Redraw dynamic controlsprivate void DrawControls(DataTable dtTable) { Hashtable htControls = new Hashtable(); try { for (int i = 0; i < dtTable.Rows.Count; i++) { //Generate in following order //1. Label, to display caption //2. And a control attached to label. DataRow drRow = dtTable.Rows[i]; Label theLabel = new Label(); theLabel.Width = new Unit(Constants.ControlSizePercentage); theLabel.Text = drRow["CAPTION"].ToString(); phControls.Controls.Add(theLabel); ViewState["Label" + i.ToString()] = theLabel.Text; //save the label control if (drRow["DATATYPE"].ToString() == "TextBox") { TextBox ctl = new TextBox(); ctl.Width = new Unit(Constants.ControlSizePercentage); ctl.ID = "objControl" + i.ToString(); phControls.Controls.Add(ctl); //Add in the hashtable htControls.Add(i, "TextBox"); } else if (drRow["DATATYPE"].ToString() == "List") { //Pull and save the ddp list. ListBox ctl = new ListBox(); ctl.Width = new Unit(Constants.ControlSizePercentage); ctl.ID = "objControl" + i.ToString(); ctl.SelectionMode = ListSelectionMode.Multiple; phControls.Controls.Add(ctl); htControls.Add(i, "List"); //Options: //1. Add list items here manually... OR //2. Get the item list from database and bind with list box. } else if (drRow["DATATYPE"].ToString() == "Date") { //add user control Control ctl = LoadControl("~/UI/UserControls/UCtlCalendar.ascx"); ctl.ID = "objControl" + i.ToString(); phControls.Controls.Add(ctl); htControls.Add(i, "Date"); } } ViewState.Add("htControls", htControls); } catch (Exception ex) { Error("Problem! " + ex.ToString()); } }
private void RedrawControls() { try { Hashtable htControls = (Hashtable)ViewState["htControls"]; for (int i = 0; i < htControls.Count; i++) { Label theLabel = new Label(); theLabel.Width = new Unit(Constants.ControlSizePercentage); theLabel.Text = ViewState["Label" + i.ToString()].ToString(); //Reload the labels. phControls.Controls.Add(theLabel); if (htControls[i].ToString() == "TextBox") //Print text box. { TextBox ctl = new TextBox(); ctl.Width = new Unit(Constants.ControlSizePercentage); ctl.ID = "objControl" + i.ToString(); phControls.Controls.Add(ctl); } else if (htControls[i].ToString() == "List") { ListBox ctl = new ListBox(); ctl.Width = new Unit(Constants.ControlSizePercentage); ctl.ID = "objControl" + i.ToString(); phControls.Controls.Add(ctl); //Set list box items, if any. } else if (htControls[i].ToString() == "Date") { //1. Load a UserControl Control ctl = LoadControl("~/UI/UserControls/UCtlCalendar.ascx"); //2. Assign an ID ctl.ID = "objControl" + i.ToString(); ((Calendar)ctl.FindControl("cldDate")).SelectedDate = DateTime.Now.Date;//Assign a default date //3. Add to PlaceHolder control phControls.Controls.Add(ctl); } } } catch (Exception ex) { Error("Problem! " + ex.ToString()); } }
STEP 4: Read from dynamically generated user controls
private string ReadTextFromControls() { StringBuilder sbResponse = new StringBuilder(); try { Hashtable htControls = (Hashtable)ViewState["htControls"]; sbResponse.Append("?"); for (int i = 0; i < htControls.Count; i++) { sbResponse.Append(ViewState["Label" + i.ToString()].ToString()); sbResponse.Append("="); if (htControls[i].ToString() == "TextBox") //Print text box. { sbResponse.Append(((TextBox)phControls.FindControl("objControl" + i.ToString())).Text); } else if (htControls[i].ToString() == "List") { ListBox ctl = ((ListBox)phControls.FindControl("objControl" + i.ToString())); for (int j = 0; j < ctl.Items.Count; j++) { if (ctl.Items[j].Selected) sbResponse.Append(ctl.Items[j].Text + ",");//make it comma separated. } sbResponse.Remove(sbResponse.ToString().Length - 1, 1); //remove the last extra comma. } else if (htControls[i].ToString() == "Date") //Print text box. { //1. Find calendar control Control ctl = phControls.FindControl("objControl" + i.ToString()); //2. Get the date string str = ((Calendar)ctl.FindControl("cldDate")).SelectedDate.ToShortDateString(); sbResponse.Append(str); } sbResponse.Append("&"); } if (sbResponse.ToString().EndsWith("&")) { sbResponse.Remove(sbResponse.ToString().Length - 1, 1);//remove the last character! } } catch (Exception ex) { Error("Problem! " + ex.ToString()); } return sbResponse.ToString(); }
Usage is same:
protected void Page_Load(object sender, EventArgs e) { if(!Page.IsPostBack) { DrawControls();//First time, just draw } else { RedrawControls();//Other times, redraw existing controls. } }
Happy Dynami’zing the controls (0;