locked
How to add multiple textboxes dynamically in a gridview with a button in a column? RRS feed

  • Question

  • User476110528 posted

    I have a requirement where I need to be able to associate an one-to-many relationship with gridview that has columns Faculty, NumberOfCourses, then Courses. The courses column needs to be able to take in multiple values. So there will be column Faculty, column NumberOfCourses, and a column Courses that contains multiple values. The trick is, that I need to be able to add more courses dynamically to this column, so basically, column Courses can have X number of courses, and they can hit a Add button in the column to add onto to existing courses or to add courses if none exist with a textbox. How can I implement this and databind it? Is this possible in a gridview? I looked into nested gridviews, and that seems to be the closest option.

    Faculty NumberOfCourses Courses
    Teacher1 3 830, 200, TEXTBOX, ADD Button
    Teacher2 2 100, TEXTBOX, ADD Button
    Monday, September 30, 2019 2:34 PM

Answers

  • User665608656 posted

    Hi Jdavila,

    According to your description, I suggest that you don't need to use nested GridViews to implement it.

    You just need to create a TemplateFiled to put textbox and buttons.

    First, I have create two tables in my datatbase which is similar to yours.

    FacultyTable:

    CoursesTable:

    If you want to display the data as the content of the tables you provide, when Binding gridview, you need to write a new SQL to combine:

    Select  s.Id, s.Faculty,
            Stuff((
                Select  ',' +  CONVERT(varchar(50), c.CourseId) 
                From    CoursesTable c
                Where   s.Id = c.FacultyId
                For     XML Path('')
            ), 1, 1, '') As Courses
    From FacultyTable s
    Group By s.Id, s.Faculty

    Here is the full code :

      protected void Page_Load(object sender, EventArgs e)
            {
                if (!IsPostBack)
                {
                    GridView1.DataSource = Bind();
                    GridView1.DataBind();
                }
            }
            public DataTable Bind()
            {
                string connstring = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
                using (SqlConnection conn = new SqlConnection(connstring))
                {
                    conn.Open();
                    string sql = @"Select  s.Id, s.Faculty,
            Stuff((
                Select  ',' +  CONVERT(varchar(50), c.CourseId) 
                From    CoursesTable c
                Where   s.Id = c.FacultyId
                For     XML Path('')
            ), 1, 1, '') As Courses
    From FacultyTable s
    Group By s.Id, s.Faculty";
                    SqlDataAdapter ad = new SqlDataAdapter(sql, conn);
                    DataSet ds = new DataSet();
                    ad.Fill(ds);
                    conn.Close();
                    return ds.Tables[0];
                }
            }
    
            protected void Button1_Click(object sender, EventArgs e)
            {
                Button addButton = sender as Button;
                int id = Convert.ToInt32(addButton.CommandArgument);
                GridViewRow gridViewRow = addButton.NamingContainer as GridViewRow;
                TextBox AddText = gridViewRow.Controls[3].FindControl("TextBox1") as TextBox;
    
                if (AddText.Visible)
                {
                    if (string.IsNullOrEmpty(AddText.Text))
                    {
                        ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "", "alert('Please enter the course you want to add!')", true);
                    }
                    else
                    {
                        AddCourses(Convert.ToInt32(AddText.Text.ToString()),id);
                        ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "", "alert('Add successfully!')", true);
                    }
                }
                else
                {
                    AddText.Visible = true;
                    Button btCancel = gridViewRow.Controls[3].FindControl("Button2") as Button;
                    btCancel.Visible = true;
                }
    
            }
            public void AddCourses(int courseId,int facultyId)
            {
                string connstring = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
                string SQLString = "insert into CoursesTable (CourseId,FacultyId) values(@CourseId,@FacultyId)"; 
                SqlParameter[] cmdParms = {
                        new SqlParameter("@CourseId",courseId),
                        new SqlParameter("@FacultyId", facultyId)};
                using (SqlConnection connection = new SqlConnection(connstring))
                {
                    using (SqlCommand cmd = new SqlCommand(SQLString, connection))
                    {
                        if (cmdParms != null)
                        {
                            foreach (SqlParameter parameter in cmdParms)
                            {
                                cmd.Parameters.Add(parameter);
                            }
                        }
                        try
                        {
                            connection.Open();
                            cmd.ExecuteNonQuery();
                           
                        }
                        catch (SqlException ex)
                        {
                            throw ex;
                        }
                        finally
                        {
                            GridView1.DataSource = Bind();
                            GridView1.DataBind();
                            connection.Close();
                        }
                    }
                }
            }
            protected void Button2_Click(object sender, EventArgs e)
            {
                Button CancelButton = sender as Button;
                GridViewRow gridViewRow = CancelButton.NamingContainer as GridViewRow;
                TextBox AddText = gridViewRow.Controls[3].FindControl("TextBox1") as TextBox;
                AddText.Visible = false;
                CancelButton.Visible = false;
            }
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <style type="text/css">
            .BorderStyle {
                border-right: 0px ;
                border-left: 0px;
            }
        </style>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
                <asp:UpdatePanel ID="UpdatePanel1" runat="server">
                    <ContentTemplate>
                        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="Id">
                            <Columns>
                                <asp:BoundField DataField="Id" HeaderText="Id" ReadOnly="True" SortExpression="Id"  Visible="false"/>
                                <asp:BoundField DataField="Faculty" HeaderText="Faculty" SortExpression="Faculty" />
                                <asp:BoundField DataField="Courses" HeaderText="Courses" SortExpression="Courses" HeaderStyle-CssClass="BorderStyle" ItemStyle-CssClass="BorderStyle" />
                                <asp:TemplateField ItemStyle-CssClass="BorderStyle" HeaderStyle-CssClass="BorderStyle">
                                    <ItemTemplate>
                                        <asp:TextBox ID="TextBox1" runat="server" Visible="false"></asp:TextBox>
                                        <asp:Button ID="Button1" runat="server" Text="Add" CommandArgument='<%#Bind("Id")%>' OnClick="Button1_Click" />
                                        <asp:Button ID="Button2" runat="server" Text="Cancel" Visible="false" OnClick="Button2_Click" />
    
                                    </ItemTemplate>
                                </asp:TemplateField>
                            </Columns>
                        </asp:GridView>
                    </ContentTemplate>
                </asp:UpdatePanel>
            </div>
        </form>
    </body>
    </html>
    

    Here is the result of this work demo:

    Best Regards,

    YongQing.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, October 1, 2019 8:04 AM

All replies

  • User475983607 posted

    This is a very common programming problem covered in most beginning level working with data tutorials. 

    The common UI design is to first select a teach then add courses to the selected teacher using a checkbox list or multi-select.

    For a GridView,  edit the teacher record.  In the edit template use a multi-select to select the courses, then click save.  Of course, you need to add logic to the GridView edit and save events.

    https://docs.microsoft.com/en-us/aspnet/web-forms/

    Monday, September 30, 2019 6:41 PM
  • User476110528 posted

    Thanks mgebhard, but I need them to be able to add courses, not select them. If they need to add a course, they should be able to click the Add button and a textbox will appear to allow them to add one. Any tips on that?

    Monday, September 30, 2019 7:11 PM
  • User475983607 posted

    Thanks mgebhard, but I need them to be able to add courses, not select them. If they need to add a course, they should be able to click the Add button and a textbox will appear to allow them to add one. Any tips on that?

    You'll need to explain the design intent and what add courses means.  IMHO, it makes little makes sense to add courses from a grid that lists teachers.  It does make sense that an instructor can have many courses.  You can express this relationship using a multi-select or check boxes.   This is a very common task in web development.

    If you truly wish to add courses, then create a new page that list the existing courses and provides a button to add a new course.

    Monday, September 30, 2019 8:14 PM
  • User665608656 posted

    Hi Jdavila,

    According to your description, I suggest that you don't need to use nested GridViews to implement it.

    You just need to create a TemplateFiled to put textbox and buttons.

    First, I have create two tables in my datatbase which is similar to yours.

    FacultyTable:

    CoursesTable:

    If you want to display the data as the content of the tables you provide, when Binding gridview, you need to write a new SQL to combine:

    Select  s.Id, s.Faculty,
            Stuff((
                Select  ',' +  CONVERT(varchar(50), c.CourseId) 
                From    CoursesTable c
                Where   s.Id = c.FacultyId
                For     XML Path('')
            ), 1, 1, '') As Courses
    From FacultyTable s
    Group By s.Id, s.Faculty

    Here is the full code :

      protected void Page_Load(object sender, EventArgs e)
            {
                if (!IsPostBack)
                {
                    GridView1.DataSource = Bind();
                    GridView1.DataBind();
                }
            }
            public DataTable Bind()
            {
                string connstring = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
                using (SqlConnection conn = new SqlConnection(connstring))
                {
                    conn.Open();
                    string sql = @"Select  s.Id, s.Faculty,
            Stuff((
                Select  ',' +  CONVERT(varchar(50), c.CourseId) 
                From    CoursesTable c
                Where   s.Id = c.FacultyId
                For     XML Path('')
            ), 1, 1, '') As Courses
    From FacultyTable s
    Group By s.Id, s.Faculty";
                    SqlDataAdapter ad = new SqlDataAdapter(sql, conn);
                    DataSet ds = new DataSet();
                    ad.Fill(ds);
                    conn.Close();
                    return ds.Tables[0];
                }
            }
    
            protected void Button1_Click(object sender, EventArgs e)
            {
                Button addButton = sender as Button;
                int id = Convert.ToInt32(addButton.CommandArgument);
                GridViewRow gridViewRow = addButton.NamingContainer as GridViewRow;
                TextBox AddText = gridViewRow.Controls[3].FindControl("TextBox1") as TextBox;
    
                if (AddText.Visible)
                {
                    if (string.IsNullOrEmpty(AddText.Text))
                    {
                        ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "", "alert('Please enter the course you want to add!')", true);
                    }
                    else
                    {
                        AddCourses(Convert.ToInt32(AddText.Text.ToString()),id);
                        ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "", "alert('Add successfully!')", true);
                    }
                }
                else
                {
                    AddText.Visible = true;
                    Button btCancel = gridViewRow.Controls[3].FindControl("Button2") as Button;
                    btCancel.Visible = true;
                }
    
            }
            public void AddCourses(int courseId,int facultyId)
            {
                string connstring = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
                string SQLString = "insert into CoursesTable (CourseId,FacultyId) values(@CourseId,@FacultyId)"; 
                SqlParameter[] cmdParms = {
                        new SqlParameter("@CourseId",courseId),
                        new SqlParameter("@FacultyId", facultyId)};
                using (SqlConnection connection = new SqlConnection(connstring))
                {
                    using (SqlCommand cmd = new SqlCommand(SQLString, connection))
                    {
                        if (cmdParms != null)
                        {
                            foreach (SqlParameter parameter in cmdParms)
                            {
                                cmd.Parameters.Add(parameter);
                            }
                        }
                        try
                        {
                            connection.Open();
                            cmd.ExecuteNonQuery();
                           
                        }
                        catch (SqlException ex)
                        {
                            throw ex;
                        }
                        finally
                        {
                            GridView1.DataSource = Bind();
                            GridView1.DataBind();
                            connection.Close();
                        }
                    }
                }
            }
            protected void Button2_Click(object sender, EventArgs e)
            {
                Button CancelButton = sender as Button;
                GridViewRow gridViewRow = CancelButton.NamingContainer as GridViewRow;
                TextBox AddText = gridViewRow.Controls[3].FindControl("TextBox1") as TextBox;
                AddText.Visible = false;
                CancelButton.Visible = false;
            }
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <style type="text/css">
            .BorderStyle {
                border-right: 0px ;
                border-left: 0px;
            }
        </style>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
                <asp:UpdatePanel ID="UpdatePanel1" runat="server">
                    <ContentTemplate>
                        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="Id">
                            <Columns>
                                <asp:BoundField DataField="Id" HeaderText="Id" ReadOnly="True" SortExpression="Id"  Visible="false"/>
                                <asp:BoundField DataField="Faculty" HeaderText="Faculty" SortExpression="Faculty" />
                                <asp:BoundField DataField="Courses" HeaderText="Courses" SortExpression="Courses" HeaderStyle-CssClass="BorderStyle" ItemStyle-CssClass="BorderStyle" />
                                <asp:TemplateField ItemStyle-CssClass="BorderStyle" HeaderStyle-CssClass="BorderStyle">
                                    <ItemTemplate>
                                        <asp:TextBox ID="TextBox1" runat="server" Visible="false"></asp:TextBox>
                                        <asp:Button ID="Button1" runat="server" Text="Add" CommandArgument='<%#Bind("Id")%>' OnClick="Button1_Click" />
                                        <asp:Button ID="Button2" runat="server" Text="Cancel" Visible="false" OnClick="Button2_Click" />
    
                                    </ItemTemplate>
                                </asp:TemplateField>
                            </Columns>
                        </asp:GridView>
                    </ContentTemplate>
                </asp:UpdatePanel>
            </div>
        </form>
    </body>
    </html>
    

    Here is the result of this work demo:

    Best Regards,

    YongQing.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, October 1, 2019 8:04 AM
  • User476110528 posted

    Sorry, the courses are not known beforehand. Is that what you mean by select box if the courses already exist?

    Thursday, October 10, 2019 3:30 PM
  • User476110528 posted

    This is the correct solution, although we decided to let the user simply add multiple courses comma delimited into one textbox. Thanks Yongqing!

    Thursday, October 10, 2019 3:31 PM