0

I am using the following code to add items to a panel but the problem is its only allowing me to add one instance of a control, I want to be able to add as many items as I want to the panel and i thought the following code would acheieve that.

 if (ctrlType.SelectedValue == "TextBox")
        {
            listElements.Add(new XElement(@"TextBox", new XElement("name"),
                                  new XElement("Type", "System.String"),
                                    new XElement("displayName", this.txtTitle.Text.ToString()),
                                    new XElement("length", txtMaxLength.Text.ToString()),
                                     new XElement("key", false),
                                     new XElement("required",  chkRequired.Checked)));


            TextBoxUserControl tb2 =
                         (TextBoxUserControl)LoadControl(@"~\UserControls\TextBoxUserControl.ascx");
            tb2.XMLText = listElements;
            tb2.Text = txtTitle.Text;
            tb2.Name = "TextBox" + " " + ctrlSource.SelectedValue.ToString() + " " + Guid.NewGuid().ToString();
            pnlControls.Controls.Add(tb2);

        }

        if (ctrlType.SelectedValue == "DropDown" && ctrlSource.SelectedValue == "0")   {
            listElements.Add(new XElement(@"ClassficationEnum", new XElement("name", "TestForm"),
                new XElement("Guid", "1f77f0ce-9e43-340f-1fd5-b11cc36c9cba"),
                                     new XElement("Type", "System.String"),
                                       new XElement("displayName", this.txtTitle.Text.ToString()),
                                       new XElement("length", txtMaxLength.Text.ToString()),
                                        new XElement("key", false),
                                        new XElement("required",  chkRequired.Checked)));


            Classfication clafficationDp =
                    (Classfication)LoadControl(@"~\UserControls\Classfication.ascx");
            clafficationDp.ID = "clafficationDp" + " " + ctrlSource.SelectedValue.ToString() + " " + Guid.NewGuid().ToString();
            clafficationDp.Text = txtTitle.Text;
            pnlControls.Controls.Add(clafficationDp);



        }
        else if (ctrlType.SelectedValue == "DropDown" && ctrlSource.SelectedValue == "1")
        {
            listElements.Add(new XElement(@"SourceEnum", new XElement("name", "TestForm"),
                new XElement("Guid", "5d59071e-69b3-7ef4-6dee-aacc5b36d898.xml"),
                                     new XElement("Type", "System.String"),
                                       new XElement("displayName", this.txtTitle.Text.ToString()),
                                       new XElement("length", txtMaxLength.Text.ToString()),
                                        new XElement("key", false),
                                        new XElement("required", chkRequired.Checked)));



            SourceEnum dpsource =
                         (SourceEnum)LoadControl(@"~\UserControls\SourceEnum.ascx");
            dpsource.ID = "DropList" + " " + ctrlSource.SelectedValue.ToString() + " " + Guid.NewGuid().ToString();
            dpsource.Text = txtTitle.Text;
            pnlControls.Controls.Add(dpsource);

        }
        UpdateActiveControl("Test", "Form Name", "Test Control", listElements);



        pnlControls.Controls.Add(new LiteralControl("<br />"));
  //      formControls = formGen.GetFormDataFromService();
        foreach (XElement formControl in listElements)
         {

             FormStructure frmstructure = new FormStructure();

             frmstructure.displayname = formControl.Element("displayName").Value;
             frmstructure.Required = Convert.ToBoolean(formControl.Element("required").Value);
             frmstructure.length = formControl.Element("length").Value;
             frmstructure.ControlType = formControl.Element("Type").Value;                


             formControls.Add(frmstructure);
         }

This is where I load the details of form controls

 public partial class _default : System.Web.UI.Page
{

    PortalContext portalContext = new PortalContext();
    DataAccess da = new DataAccess();
    FormGenerator formGen = new FormGenerator();
    List<FormStructure> formControls = new List<FormStructure>();
    List<XElement> listElements = new List<XElement>();

    protected void Page_Load(object sender, EventArgs e)
    {
        da.SqlInstanceName = "CDDEVSVR-SQL";
        da.PortalDatabaseName = "PortalCms";
        da.IntegratedSecurity = true;
        SetEntityContextConnectionStrings();

        if (!IsPostBack)
        {
            formControls = formGen.GetFormDataFromService();
        }
        foreach (FormStructure formControl in formControls)
        {


            if (formControl.ControlType == "TextBox")
            {
                listElements.Add(new XElement(@"TextBox", new XElement("name"),
                                new XElement("Type", "System.String"),
                                  new XElement("displayName", this.txtTitle.Text.ToString()),
                                  new XElement("length", txtMaxLength.Text.ToString()),
                                   new XElement("key", false),
                                   new XElement("required", chkRequired.Checked)));



                TextBoxUserControl textBoxControl =
                    (TextBoxUserControl)LoadControl(@"~\UserControls\TextBoxUserControl.ascx");
                textBoxControl.XMLText = listElements;
                textBoxControl.Text = formControl.displayname;

                pnlControls.Controls.Add(textBoxControl);
                pnlControls.Controls.Add(new LiteralControl("<br />"));


            }

            if (formControl.ControlType == "DropDown")
            {
                listElements.Add(new XElement(@"ClassficationEnum", new XElement("name", "TestForm"),
                     new XElement("Guid", "1f77f0ce-9e43-340f-1fd5-b11cc36c9cba"),
                                          new XElement("Type", "System.String"),
                                            new XElement("displayName", this.txtTitle.Text.ToString()),
                                            new XElement("length", txtMaxLength.Text.ToString()),
                                             new XElement("key", false),
                                             new XElement("required", chkRequired.Checked)));


                SourceEnum dpsource =
                     (SourceEnum)LoadControl(@"~\UserControls\SourceEnum.ascx");
                dpsource.ID = "DropList" + " " + ctrlSource.SelectedValue.ToString() + " " + Guid.NewGuid().ToString();
                dpsource.Text = formControl.displayname;
                pnlControls.Controls.Add(dpsource);




            }
        }
    }
c-sharp-and-swiftui-devni
  • 3,743
  • 4
  • 39
  • 100

2 Answers2

1

I have done some amateur level work dynamically adding user controls in a collection-like manner to ASP.NET web forms and was able to get it to work correctly. If your problem is as @rene suggests where you are only seeing one control persist through postback, it might be because of a page render process problem as described in this question answer and as @ovm suggests; each page render has to re-generate the controls, I was able to do that using arrays stored in a for-purpose session variable.

That said, while working on the feature, several blog posts suggested that it was not a terrific idea, and seeing the way it works in the page generation and rendering, I agree. I don't expect to have an easy time ajaxing the dynamic section of the page or otherwise improving it later. The common (two blogs, maybe) workaround was to design to have all the controls you could possibly need already built into the page, then hide and don't serve the ones that you don't need for a given page render. HTH

Community
  • 1
  • 1
stackuser83
  • 2,012
  • 1
  • 24
  • 41
  • Preloading and hiding all but the active control in OnInit is what I'm doing in bigger WebForm apps too. But there is also one drawback: if those controls expose events themselves than it can become really cumbersome to manage postbacks. Because those controls are probably added during a Postback, the common (mis?)conception of solely using Page.IsPostback in the Page_Load function can get you into trouble. But this comment is really just a sidenote about WebForms architecture. To the OP: I would strongly suggest to use MVC instead, or keep the UserControl structure as simple as possible. – ovm Jul 16 '14 at 15:11
  • @ovm my problem is the logic its only ever getting one control in the when i click the add button i dont no why – c-sharp-and-swiftui-devni Jul 16 '14 at 15:54
  • @ovm see my edit where i am loading the info first maybe you can sheed some light on it – c-sharp-and-swiftui-devni Jul 16 '14 at 15:59
  • @stackUser83 would you have some example code of that implmentation as I think thats what I am running against – c-sharp-and-swiftui-devni Jul 16 '14 at 16:11
  • I am not sure that is the biggest of your problems. Are you sure your `formControls = formGen.GetFormDataFromService();` is returning all of the expected controls? If the dynamic control data isn't saved in time for the next page render method call, that would help explain the missing controls. – stackuser83 Jul 16 '14 at 16:40
0

You have to keep track of all controls that you have already added to the panel and re-add them on postback.

If those controls should be Event-Aware, you should add them during the OnInit Phase of the page lifecycle.

update

Your initialization of the formControls variable is not guaranteed to persist each postback across multiple requests. What you could do is keep track of the FormStructure instances in the HttpContext.Current.Cache and recreate the controls during the OnInit stage based on the FormStructures in the Cache.

private List<FormStructure> GetFormStructureStore () {
  IList<FormStructure> formControls = (IList<FormStructure>)HttpContext.Current.Cache["FormControlsKey"];
  if(formControls == null)
  {
    formControls = new List<FormStructure>();
    HttpContext.Current.Cache.Add(formControls);
  }
  return formControls;
}

protected override void OnInit(EventArgs e)
{
  IList<FormStructure> formControls = GetFormStructureStore();
  // load the controls and add them to the Controls collection
  // ...
}

You can now use this method to get the formControls from Cache and remove the Page level variable.

//List<FormStructure> formControls = new List<FormStructure>();

Also, can you show us what

formGen.GetFormDataFromService();

is actually returning?

I am asking this because even if the contents of formControls is lost at some point in the Session, if GetFormDataFromService() returns multiple FormStructures, those should actually be visible.

ovm
  • 2,452
  • 3
  • 28
  • 51