Pramod Niralakeri
Pramod Niralakeri

Reputation: 43

how to create a dynamic textbox from dynamically created drop down list in c#

i want to create the number of dynamic text boxes (values selected in drop down list ranging from 1 to 5)

note : drop down list list is also a dynamically created control

here sample code :

    Table table=new Table();

    for (int i = 1; i <= 5; i++)
    {
        TableRow row = new TableRow();
        TableCell cell = new TableCell();

        DropDownList drp_splzn = new DropDownList();

        drp_splzn.ID = i.ToString();
        drp_splzn.Items.Add("-SELECT SPECIALIZATION-");
        drp_splzn.Items.Add(new ListItem("1", "1"));
        drp_splzn.Items.Add(new ListItem("2", "2"));
        drp_splzn.Items.Add(new ListItem("3", "3"));
        drp_splzn.Items.Add(new ListItem("4", "4"));
        drp_splzn.Items.Add(new ListItem("5", "5"));


        cell.Controls.Add(drp_splzn);

        row.Cells.Add(cell);
        table.Rows.Add(row);
    }

i want textboxes to be created followed by respected drop down list... i know thats possible using postback and drop down list changed event... but i couldnot figure it out

Upvotes: 1

Views: 3103

Answers (3)

alainlompo
alainlompo

Reputation: 4434

Here is a solution to the final issue.

The following picture is an illustration (you may change the textboxes contents and the new values will be kept between postbacks):

many selections

We are now facing the need to keep the already displayed textboxes displayedand also to keep the values they hold. The key to doing this is using the ViewState object. We will do that by enabling it on every control of which we want its state to be persisted. On the other hand ASP .NET's engine will not recreate our controls for us, but when they are available it will use the ViewState mechanism against them.

So first of all let's create a Dictionary object. We will use it to hold two informations. Number 1 a useddropdownlist and number 2 the selected value on that dropdownlist. We create it as a static variable just like we did the boolean hasDropDowns

public partial class WebForm1 : System.Web.UI.Page
{
    static bool hasDropDowns = false;
    static Dictionary<int, int> textBoxesStateDictionnary = new Dictionary<int, int>();

...

We will use the dropdownlist's id as a key and the selected value on that dropdownlist as the associated value.

Then we need to change our selectindex changed event handler. When a value is selected and we create the textboxes we need to add a new entry in the Dictionary. Here is the new version of the selectindex changed event handler

 void drp_splzn_SelectedIndexChanged(object sender, EventArgs e)
    {

        DropDownList chosenDropDown = (DropDownList)sender;

        Int32 pickedValue = Int32.Parse(chosenDropDown.SelectedValue);

        Table table = // new Table();
         (Table)Page.Form.FindControl("table" + chosenDropDown.ID);

        for (int i = 0; i < pickedValue; i++)
        {

            TableRow row = new TableRow();
            TableCell cell = new TableCell();
            cell.Attributes.Add("runat", "server");

            TextBox txt_splzn = new TextBox();

            txt_splzn.ID = "txtB_" + chosenDropDown.ID + "_" + i.ToString();
            txt_splzn.Text = "Text Number " + i.ToString();
            txt_splzn.EnableViewState = true;

            cell.Controls.Add(txt_splzn);

            row.Cells.Add(cell);
            table.Rows.Add(row);

        }

        textBoxesStateDictionnary.Add(Int32.Parse(chosenDropDown.ID), Int32.Parse(chosenDropDown.SelectedValue));

    }

As you can see in the last line of code the key is the chosen drop down list's ID and the corresponding value, it's selected value.

Also we had to change the textbox id since the previous ids were made of a litteral and the selected value. If we had kept it the same, the Page.Form.FindControl method would raise an exception: the IDs are to be unique.

Now we need to impact the Page_Load event handler. Right after we recreate a Drop down list we look into the Dictionary to see if there is a corresponding entry (using it's ID). If there is, we recreate as much Textboxes as indicated by the corresponding value in the dictionary's entry. And then we trust the ViewState to do it's work since when we created the Textboxes we activated the ViewState (see txt_splzn.EnableViewState = true;)

Here is the Page_Load event handler's code

 protected void Page_Load(object sender, EventArgs e)
    {

        if (Page.IsPostBack)
        {
            if (!hasDropDowns)
            {
                return;
            }

            Table table = new Table();

            for (int i = 1; i <= 5; i++)
            {
                TableRow row = new TableRow();
                TableCell cell = new TableCell();
                cell.Attributes.Add("runat", "server");

                DropDownList drp_splzn = new DropDownList();

                drp_splzn.ID = i.ToString();
                drp_splzn.Items.Add("-SELECT SPECIALIZATION-");
                drp_splzn.Items.Add(new ListItem("1", "1"));
                drp_splzn.Items.Add(new ListItem("2", "2"));
                drp_splzn.Items.Add(new ListItem("3", "3"));
                drp_splzn.Items.Add(new ListItem("4", "4"));
                drp_splzn.Items.Add(new ListItem("5", "5"));

                drp_splzn.SelectedIndexChanged += drp_splzn_SelectedIndexChanged;
                drp_splzn.AutoPostBack = true;
                drp_splzn.EnableViewState = true;


                cell.Controls.Add(drp_splzn);

                row.Cells.Add(cell);
                table.Rows.Add(row);

                TableRow rowT = new TableRow();
                TableCell cellT = new TableCell();
                cellT.Attributes.Add("runat", "server");

                Table table2 = new Table();

                table2.ID = "table" + i.ToString();


                int retrievedValue = -1;
                if (textBoxesStateDictionnary.TryGetValue(i, out retrievedValue))
                {
                    for (int j = 0; j < retrievedValue; j++)
                    {
                        // Recreate them
                        TableRow rowTT = new TableRow();
                        TableCell cellTT = new TableCell();
                        cellTT.Attributes.Add("runat", "server");

                        TextBox txt_splzn = new TextBox();

                        txt_splzn.ID = "txtB_" + i +"_" + j.ToString();

                        txt_splzn.EnableViewState = true;

                        cellTT.Controls.Add(txt_splzn);
                        rowTT.Controls.Add(cellTT);
                        table2.Controls.Add(rowTT);

                    }

               }

                cellT.Controls.Add(table2);

                rowT.Cells.Add(cellT);
                table.Rows.Add(rowT);
            }

            this.Controls.Add(table);

            Page.Form.Controls.Add(table);

        }
        else
        {

        }

    }

And that's it.

Upvotes: 1

alainlompo
alainlompo

Reputation: 4434

Here is the solution to your last issue. It is exactly the implementation of the idea that I shared with you as comment.

Here are some illustration images and the code below

Illustration_1

Illustration_2

First in the protected void Button1_Clickmethod, I add an empty table under each dropdownlist. Since it is empty it won't show up at first.

Here is the code for that:

protected void Button1_Click(object sender, EventArgs e)
    {

        Table table = new Table();

        for (int i = 1; i <= 5; i++)
        {
            TableRow row = new TableRow();
            TableCell cell = new TableCell();
            cell.Attributes.Add("runat", "server");

            DropDownList drp_splzn = new DropDownList();

            drp_splzn.ID = i.ToString();
            drp_splzn.Items.Add("-SELECT SPECIALIZATION-");
            drp_splzn.Items.Add(new ListItem("1", "1"));
            drp_splzn.Items.Add(new ListItem("2", "2"));
            drp_splzn.Items.Add(new ListItem("3", "3"));
            drp_splzn.Items.Add(new ListItem("4", "4"));
            drp_splzn.Items.Add(new ListItem("5", "5"));

            drp_splzn.SelectedIndexChanged += drp_splzn_SelectedIndexChanged;
            drp_splzn.AutoPostBack = true;
            drp_splzn.EnableViewState = true;


            cell.Controls.Add(drp_splzn);

            row.Cells.Add(cell);
            table.Rows.Add(row);

            TableRow rowT = new TableRow();
            TableCell cellT = new TableCell();
            cellT.Attributes.Add("runat", "server");

            Table table2 = new Table();

            table2.ID = "table" + i.ToString();

            cellT.Controls.Add(table2);

            rowT.Cells.Add(cellT);
            table.Rows.Add(rowT);



        }

         this.Controls.Add(table);

        Page.Form.Controls.Add(table);
        hasDropDowns = true;
    }

Of course you have to duplicate these change in the Page_Loadas I did here:

 protected void Page_Load(object sender, EventArgs e)
    {

        if (Page.IsPostBack)
        {
            if (!hasDropDowns)
            {
                return;
            }

            Table table = new Table();

            for (int i = 1; i <= 5; i++)
            {
                TableRow row = new TableRow();
                TableCell cell = new TableCell();
                cell.Attributes.Add("runat", "server");

                DropDownList drp_splzn = new DropDownList();

                drp_splzn.ID = i.ToString();
                drp_splzn.Items.Add("-SELECT SPECIALIZATION-");
                drp_splzn.Items.Add(new ListItem("1", "1"));
                drp_splzn.Items.Add(new ListItem("2", "2"));
                drp_splzn.Items.Add(new ListItem("3", "3"));
                drp_splzn.Items.Add(new ListItem("4", "4"));
                drp_splzn.Items.Add(new ListItem("5", "5"));

                drp_splzn.SelectedIndexChanged += drp_splzn_SelectedIndexChanged;
                drp_splzn.AutoPostBack = true;
                drp_splzn.EnableViewState = true;


                cell.Controls.Add(drp_splzn);

                row.Cells.Add(cell);
                table.Rows.Add(row);

                TableRow rowT = new TableRow();
                TableCell cellT = new TableCell();
                cellT.Attributes.Add("runat", "server");

                Table table2 = new Table();

                table2.ID = "table" + i.ToString();

                cellT.Controls.Add(table2);

                rowT.Cells.Add(cellT);
                table.Rows.Add(rowT);
            }

            this.Controls.Add(table);

            Page.Form.Controls.Add(table);

        }
        else
        {

        }



    }

And finally in the void drp_splzn_SelectedIndexChangedinstead of instanciating a new Table with Table table = new Table(); we replace this line of code with a code that retrieves the previous table control. the chosenDropDownthat we retrieved in the first line of this method will help us: it's ID is the corresponding number. Therefore the ID to lookup is "table" + chosenDropDown.ID Also at the end of this method we don't have to add this table since it is already part of the page. So I have commented the Page.Form.Controls.Add(table);line of code

Here is the corresponding code:

void drp_splzn_SelectedIndexChanged(object sender, EventArgs e)
{

        DropDownList chosenDropDown = (DropDownList)sender;

        Int32 pickedValue = Int32.Parse(chosenDropDown.SelectedValue);

        Table table = // new Table();
         (Table)Page.Form.FindControl("table" + chosenDropDown.ID);

        for (int i = 0; i < pickedValue; i++)
        {

            TableRow row = new TableRow();
            TableCell cell = new TableCell();
            cell.Attributes.Add("runat", "server");

            TextBox txt_splzn = new TextBox();

            txt_splzn.ID = "txtB" + i.ToString();
            txt_splzn.Text = "Text Number " + i.ToString();

            cell.Controls.Add(txt_splzn);

            row.Cells.Add(cell);
            table.Rows.Add(row);

        }

        //Page.Form.Controls.Add(table);

        Response.Write("Change occured...");


    }

Upvotes: 0

alainlompo
alainlompo

Reputation: 4434

I understand you have dynamically added dropdown list and you want to create text boxes depending on the selected value on a dropdownlist

First I added a button a dynamically create the DropDownlist objects after clicking on the button

 <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Make DropDowns" />

Then I create the DropDownlist inside the Button_Click handler event (this event handler can be created simply by double - clicking on this button which is static)

All I am doing in this handler is to use your dropdown list creation code and then add the table in the controls of the page's form object. Otherwise you have an error message that tells you you need to put it in a runat = serverlike form.

I am also using a static boolean variable that allows me to keep the information that the DropDownlist have been created

Here is this event's handler code

 protected void Button1_Click(object sender, EventArgs e)
    {

        Table table = new Table();

        for (int i = 1; i <= 5; i++)
        {
            TableRow row = new TableRow();
            TableCell cell = new TableCell();
            cell.Attributes.Add("runat", "server");

            DropDownList drp_splzn = new DropDownList();

            drp_splzn.ID = i.ToString();
            drp_splzn.Items.Add("-SELECT SPECIALIZATION-");
            drp_splzn.Items.Add(new ListItem("1", "1"));
            drp_splzn.Items.Add(new ListItem("2", "2"));
            drp_splzn.Items.Add(new ListItem("3", "3"));
            drp_splzn.Items.Add(new ListItem("4", "4"));
            drp_splzn.Items.Add(new ListItem("5", "5"));

            drp_splzn.SelectedIndexChanged += drp_splzn_SelectedIndexChanged;
            drp_splzn.AutoPostBack = true ;
            drp_splzn.EnableViewState = true;


            cell.Controls.Add(drp_splzn);

            row.Cells.Add(cell);
            table.Rows.Add(row);
        }

        this.Controls.Add(table);

        Page.Form.Controls.Add(table);
        hasDropDowns = true;
    }

So my boolean variable is called hasDropDownsand is set to true once the dropdown controls are added. This will be usefull to handle the fact that the Http protocole is stateless and therefore we will need to handler ourselves the state of our controls. Otherwise after the page is Postback their state is cleared and ASP .NET engine won't be able to find the control that trigger the Post back event nore it state and we will have every dynamic control's state lost.

As you can see when I created the dropdownlist I also attached a click event handler on them and made them autopostback = true. That way they will trigger the post back as soon as their value change. This is to demonstrate how to solve the issue, you may customize it as you want to.

Now the dropdownlist selectindexchanged event handler

void drp_splzn_SelectedIndexChanged(object sender, EventArgs e)
    {
        DropDownList chosenDropDown = (DropDownList)sender;
        Int32 pickedValue = Int32.Parse(chosenDropDown.SelectedValue);
        Table table = new Table();

        for (int i = 0; i < pickedValue; i++)
        {

            TableRow row = new TableRow();
            TableCell cell = new TableCell();
            cell.Attributes.Add("runat", "server");

            TextBox txt_splzn = new TextBox();

            txt_splzn.ID = "txtB" +  i.ToString();
            txt_splzn.Text = "Text Number " + i.ToString();

            cell.Controls.Add(txt_splzn);

            row.Cells.Add(cell);
            table.Rows.Add(row);

        }

        Page.Form.Controls.Add(table);

        Response.Write("Change occured...");


    }

As you can see in the code it created as many textboxes as the selected value in the dropdown list and I put a simple text in the Text properties of these textboxes. I also gave them unique IDs.

Again we add the table to the Page's form control.

Now we need to handle the PostBack phenomenon correctly. In Asp.Net and because HTTP is stateless the engine allows us to process two kinds of Page Load. The page load that occurs the first time: in that case Page.IsPostback is false (first load) and the Page Load that occurs all the other times (in that case Page.IsPostBack is true)

So here when the Page is PostBack and hasDropDowns is true then it means that I have already gone through the process of creating the dynamic dropdowns and assigning them selectindex change handlers, therefore to have a consistent state I need to recreated them exactly as I did the first time. Then and only then will ASP.NET be able to correctly bind them to the selectindexchange event handler and process the event correctly.

Here is the Page.Load event handler's code along with the declaration of the hasDropDowns static boolean variable

 static bool hasDropDowns = false;
    protected void Page_Load(object sender, EventArgs e)
    {

        if (Page.IsPostBack)
        {
            if (!hasDropDowns)
            {
                return;
            }

            Table table = new Table();

            for (int i = 1; i <= 5; i++)
            {
                TableRow row = new TableRow();
                TableCell cell = new TableCell();
                cell.Attributes.Add("runat", "server");

                DropDownList drp_splzn = new DropDownList();

                drp_splzn.ID = i.ToString();
                drp_splzn.Items.Add("-SELECT SPECIALIZATION-");
                drp_splzn.Items.Add(new ListItem("1", "1"));
                drp_splzn.Items.Add(new ListItem("2", "2"));
                drp_splzn.Items.Add(new ListItem("3", "3"));
                drp_splzn.Items.Add(new ListItem("4", "4"));
                drp_splzn.Items.Add(new ListItem("5", "5"));

                drp_splzn.SelectedIndexChanged += drp_splzn_SelectedIndexChanged;
                drp_splzn.AutoPostBack = true;
                drp_splzn.EnableViewState = true;


                cell.Controls.Add(drp_splzn);

                row.Cells.Add(cell);
                table.Rows.Add(row);
            }

            this.Controls.Add(table);

            Page.Form.Controls.Add(table);

        }
        else
        {

        }



    }

Here are some images that shows that it is working fine.

The dropdownlist

Selecting a value

The result

Upvotes: 0

Related Questions