Editable column in gridview

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • JohnShell
    New Member
    • Nov 2009
    • 5

    #1

    Editable column in gridview

    Hi,

    I created an ASP.NET 4 columns gridview programmaticall y using VB.NET. The first two columns are bound to checkboxes and a database. When the user selects one or more checkboxes the database information populates the first two columns. I want the user to be able to enter data into the second two columns' rows. Is this possible and, if it is, how is it accomplished? Following is the code for the gridview:

    Code:
    Private Sub BindGridView()
            'Dim da As New DataLayer.SqlDataAccess
            'Dim sql As String = "Select * from categories"
            Dim dt As New DataTable '= da.GetDataTable(sql)
            dt.Columns.Add(New DataColumn("Branch"))
            dt.Columns.Add(New DataColumn("Team"))
            dt.Columns.Add(New DataColumn("Reg Hrs Allocated"))
            dt.Columns.Add(New DataColumn("OT Hrs Allocated"))
            dt.Columns(2).ReadOnly = False
            dt.Columns(3).ReadOnly = False
            Dim PlaceHolder As DataRow = dt.NewRow
            dt.Rows.Add(PlaceHolder)
    
            Dim RS As SqlDataReader = ClsData.getRecordSet("Select Distinct ISNULL([Team], 'N/A') As Team, [Branch_Initials] As Branch From dbo.Employees Order By Branch_Initials", ClsData.ConnectionString)
            If RS.HasRows Then
                While RS.Read
                    System.Diagnostics.Debug.Print(RS("Branch") & ("Team"))
                    Dim rw As DataRow = dt.NewRow
                    rw.Item("Branch") = RS("Branch")
                    rw.Item("Team") = RS("Team")
                    dt.Rows.Add(rw)
                End While
            End If
            grdAsgnTm.DataSource = dt
            grdAsgnTm.DataBind()
            For i As Integer = 1 To grdAsgnTm.Rows.Count - 1
                grdAsgnTm.Rows.Item(i).Visible = False
            Next
    
        End Sub
    Thanks - John
    Last edited by Frinavale; Nov 9 '09, 03:45 PM. Reason: Please post code in [code] ... [/code] tags. Added code tags.
  • Frinavale
    Recognized Expert Expert
    • Oct 2006
    • 9749

    #2
    You can let the user edit information displayed in a GridView.
    You have to provide an EditTemplateIte m for each column that you want to let the user edit.

    All the information you need on GridViews and any other .NET controls can be found in the MSDN Library. This resource should get you pointed in the right direction....th ere are multiple articles on GridViews there. I recommend bookmarking the MSDN Library and using it as your primary resource when developing in .NET.

    -Frinny

    Comment

    • Frinavale
      Recognized Expert Expert
      • Oct 2006
      • 9749

      #3
      What have you tried so far to get the second 2 columns to be editable?

      Have you tried using a TemplateField.I temTemplate to display TextBoxes for the content displayed in the GridView?

      Comment

      • JohnShell
        New Member
        • Nov 2009
        • 5

        #4
        Thanks again. Read the info from your link - not really understood. This is what I did - all of it:
        Code:
        Imports System.Data.SqlClient
        Imports System.Data
        
        Partial Class TMS_Site_ProjectNewAsgnTeam
            Inherits System.Web.UI.Page
        
            Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles form2.Load
                txtBrProj.Text = Session("ddlRasText")
                txtBrTmRegHrs.Text = Session("txtProjRegHrsAl")
                txtBrTmOTHrs.Text = Session("txtProjOTHrsAl")
                txtBrTmStartDate.Text = Session("StrtDte")
                txtBrTmEndDate.Text = Session("EndDte")
                BindGridView()
        
            End Sub
        
            Private Sub BindGridView()
                'Dim da As New DataLayer.SqlDataAccess
                'Dim sql As String = "Select * from categories"
                Dim dt As New DataTable '= da.GetDataTable(sql)
                dt.Columns.Add(New DataColumn("Branch"))
                dt.Columns.Add(New DataColumn("Team"))
                dt.Columns.Add(New DataColumn("Reg Hrs Allocated"))
                dt.Columns.Add(New DataColumn("OT Hrs Allocated"))
                dt.Columns(2).ReadOnly = False
                dt.Columns(3).ReadOnly = False
                Dim PlaceHolder As DataRow = dt.NewRow
                dt.Rows.Add(PlaceHolder)
        
                Dim RS As SqlDataReader = ClsData.getRecordSet("Select Distinct ISNULL([Team], 'N/A') As Team, [Branch_Initials] As Branch From dbo.Employees Order By Branch_Initials", ClsData.ConnectionString)
                If RS.HasRows Then
                    While RS.Read
                        System.Diagnostics.Debug.Print(RS("Branch") & ("Team"))
                        Dim rw As DataRow = dt.NewRow
                        rw.Item("Branch") = RS("Branch")
                        rw.Item("Team") = RS("Team")
                        dt.Rows.Add(rw)
                    End While
                End If
                grdAsgnTm.DataSource = dt
                grdAsgnTm.DataBind()
                For i As Integer = 1 To grdAsgnTm.Rows.Count - 1
                    grdAsgnTm.Rows.Item(i).Visible = False
                Next
        
            End Sub
        
            Protected Sub btnSubmitAsgnTeam_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSubmitAsgnTeam.Click
                Session("txtBrProj") = txtBrProj.Text
                Session("txtBrTmRegHrs") = txtBrTmRegHrs.Text
                Session("txtBrTmOTHrs") = txtBrTmOTHrs.Text
                Session("txtBrTmStartDate") = txtBrTmStartDate.Text
                Session("txtBrTmEndDate") = txtBrTmEndDate.Text
                Response.Redirect("ProjectNewAsgnMmbr.aspx")
            End Sub
            
            Protected Sub Branch_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles chkDVTT.CheckedChanged, chkLM.CheckedChanged, chkVEB.CheckedChanged, chkVMB.CheckedChanged, chkVUB.CheckedChanged
                Dim TempValues As String = ""
                If chkDVTT.Checked = True Then
                    TempValues += "'DVTT', "
                    txtDVTTRegHrs.Enabled = True
                    txtBrDVTTOTHrs.Enabled = True
                Else
                    txtDVTTRegHrs.Enabled = False
                    txtBrDVTTOTHrs.Enabled = False
                End If
        
                If chkLM.Checked = True Then
                    TempValues += "'LM', "
                    txtBRLMRegHrs.Enabled = True
                    txtBrLMOTHrs.Enabled = True
                Else
                    txtBRLMRegHrs.Enabled = False
                    txtBrLMOTHrs.Enabled = False
                End If
        
                If chkVEB.Checked = True Then
                    TempValues += "'VEB', "
                    txtBrVEBRegHrs.Enabled = True
                    txtBrVEBOTHrs.Enabled = True
                Else
                    txtBrVEBRegHrs.Enabled = False
                    txtBrVEBOTHrs.Enabled = False
                End If
        
                If chkVMB.Checked = True Then
                    TempValues += "'VMB', "
                    txtBrVMBRegHrs.Enabled = True
                    txtBrVMBOTHrs.Enabled = True
                Else
                    txtBrVMBRegHrs.Enabled = False
                    txtBrVMBOTHrs.Enabled = False
                End If
        
                If chkVUB.Checked = True Then
                    TempValues += "'VUB', "
                    txtBrVUBRegHrs.Enabled = True
                    txtBrVUBOTHrs.Enabled = True
                Else
                    txtBrVUBRegHrs.Enabled = False
                    txtBrVUBOTHrs.Enabled = False
                End If
        
                If TempValues <> "" Then
                    TempValues = TempValues.Substring(0, TempValues.Length - 2)
                    grdAsgnTm.Rows.Item(0).Visible = False
                Else
                    grdAsgnTm.Rows.Item(0).Visible = True
                End If
        
        
                For i As Integer = 1 To grdAsgnTm.Rows.Count - 1
                    If TempValues.Contains(grdAsgnTm.Rows.Item(i).Cells(0).Text) Then
                        grdAsgnTm.Rows.Item(i).Visible = True
                    Else
                        grdAsgnTm.Rows.Item(i).Visible = False
                    End If
        
                Next
            End Sub
        End Class
        Last edited by Frinavale; Nov 9 '09, 07:11 PM. Reason: Please post code in [code] ... [/code] tags. Added code tags.

        Comment

        • Frinavale
          Recognized Expert Expert
          • Oct 2006
          • 9749

          #5
          I should caution you that if you bind data to your GridView in the PageLoad event you will lose the data entered by the user. I would put that in the Page PreRender event if I were you to avoid this problem....but that's not the problem (yet).

          In your ASP code you have a GridView that probably looks something like the following:
          Code:
          <asp:GridView ID="grdAsgnTm" runat="server"  AllowPaging="true" AutoGenerateColumns="true" AllowSorting="true">
          
          </asp:GridView>
          You can supply "templates" to tell the GridView how to display the data.
          You use the TemplateField to do this.

          For each column create a TemplateField and tell it how the data should be displayed when the user is viewing the data or editing the data.

          For example:
          Code:
          <asp:GridView ID="grdAsgnTm" runat="server"  AllowPaging="true" AutoGenerateColumns="true" AllowSorting="true">
            <Columns>
              <asp:TemplateField HeaderText="Branch">
                <ItemTemplate>
                  <%#Eval("Branch")%>
                </ItemTemplate>
                <EditItemTemplate>
                </EditItemTemplate>
              </asp:TemplateField>
          
              <asp:TemplateField HeaderText="Team">
                <ItemTemplate>
                  <%#Eval("Team")%>
                </ItemTemplate>
                <EditItemTemplate>
                </EditItemTemplate>
              </asp:TemplateField>
           
             <asp:TemplateField HeaderText="Reg Hrs Allocated">
                <ItemTemplate>
                  <asp:TextBox ID="TxtRegHrsAllocated" runat="server" Text='<%#Bind("Reg Hrs Allocated")%>'></asp:TextBox>
                </ItemTemplate>
                <EditItemTemplate>
                </EditItemTemplate>
              </asp:TemplateField>
          
          <asp:TemplateField HeaderText="OT Hrs Allocated">
                <ItemTemplate>
                  <asp:TextBox ID="TxOTHrsAllocated" runat="server" Text='<%#Bind("OT Hrs Allocated")%>'></asp:TextBox>
                </ItemTemplate>
                <EditItemTemplate>
                </EditItemTemplate>
              </asp:TemplateField>
          
            </Columns>
          </asp:GridView>
          Notice how I have set the GridView's AutoGenerateCol umns to False. Now the columns are not automatically created for me. Instead, the GridView will use the columns that I have specified in the <Columns></Columns> section.

          I have specified that 4 columns. These columns are TemplateFields. Within each column/TemplateField I have told the GridView what controls to use to display the data that the GridView is being bound to.

          The first 2 columns will just display text.
          The next to columns will display the data in TextBoxes.

          Does this make sense so far?

          -Frinny

          Comment

          • JohnShell
            New Member
            • Nov 2009
            • 5

            #6
            gridview

            Thank you very much.

            What you stated makes sense and I shall try it tomorrow.

            John

            Comment

            • JohnShell
              New Member
              • Nov 2009
              • 5

              #7
              I managed to get the gridview working the way I want by coding the following:
              For the BindGridView() subroutine I added text boxes to the respective columns using the appropriate index number identifiers. I then captured the user entries so that I could carry the data to the next session (web page in this instance) and propagate the information.
              I prefer to do as little as possible with ASP.NET and provide the site's functionality via VB.NET. That is why I did not more completely define the gridview in ASP.

              Thank you for your help.

              Code:
               Private Sub BindGridView()
                      'Dim da As New DataLayer.SqlDataAccess
                      'Dim sql As String = "Select * from categories"
                      Dim dt As New DataTable '= da.GetDataTable(sql)
                      dt.Columns.Add(New DataColumn("Branch"))
                      dt.Columns.Add(New DataColumn("Team"))
                      dt.Columns.Add(New DataColumn("Reg Hrs Allocated"))
                      dt.Columns.Add(New DataColumn("OT Hrs Allocated"))
                      Dim PlaceHolder As DataRow = dt.NewRow
                      dt.Rows.Add(PlaceHolder)
              
                      Dim RS As SqlDataReader = ClsData.getRecordSet("Select Distinct ISNULL([Team], 'N/A') As Team, [Branch_Initials] As Branch From dbo.Employees Order By Branch_Initials", ClsData.ConnectionString)
                      If RS.HasRows Then
                          While RS.Read
                              System.Diagnostics.Debug.Print(RS("Branch") & ("Team"))
                              Dim rw As DataRow = dt.NewRow
                              rw.Item("Branch") = RS("Branch")
                              rw.Item("Team") = RS("Team")
                              dt.Rows.Add(rw)
                          End While
                      End If
                      grdAsgnTm.DataSource = dt
                      grdAsgnTm.DataBind()
                      For i As Integer = 1 To grdAsgnTm.Rows.Count - 1
                          grdAsgnTm.Rows.Item(i).Visible = False
                          grdAsgnTm.Rows.Item(i).Cells(2).Controls.Add(New TextBox)
                          grdAsgnTm.Rows.Item(i).Cells(3).Controls.Add(New TextBox)
                          DirectCast(grdAsgnTm.Rows.Item(i).Cells(2).Controls(0), TextBox).Text = 0
                          DirectCast(grdAsgnTm.Rows.Item(i).Cells(3).Controls(0), TextBox).Text = 0
                      Next
              
                  End Sub
              
                  Protected Sub btnSubmitAsgnTeam_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSubmitAsgnTeam.Click
                      Session("txtBrProj") = txtBrProj.Text
                      Session("txtBrTmRegHrs") = txtBrTmRegHrs.Text
                      Session("txtBrTmOTHrs") = txtBrTmOTHrs.Text
              
                      Dim BranchData As String = ""
                      If chkDVTT.Checked = True Then
                          BranchData += "DVTT,"
                          BranchData += txtDVTTRegHrs.Text & ","
                          BranchData += txtBrDVTTOTHrs.Text & "|"
                      
                      End If
              
                      If chkLM.Checked = True Then
                          BranchData += "LM,"
                          BranchData += txtBRLMRegHrs.Text & ","
                          BranchData += txtBrLMOTHrs.Text & "|"
                      
                      End If
              
                      If chkVEB.Checked = True Then
                          BranchData += "VEB,"
                          BranchData += txtBrVEBRegHrs.Text & ","
                          BranchData += txtBrVEBOTHrs.Text & "|"
                      
                      End If
              
                      If chkVMB.Checked = True Then
                          BranchData += "VMB,"
                          BranchData += txtBrVEBRegHrs.Text & ","
                          BranchData += txtBrVEBOTHrs.Text & "|"
                      End If
              
                      If chkVUB.Checked = True Then
                          BranchData += "VUB,"
                          BranchData += txtBrVUBRegHrs.Text & ","
                          BranchData += txtBrVUBOTHrs.Text & "|"
                      End If
              
                      Session("BranchData") = BranchData
                      Dim grdTmData As String = ""
                      For i As Integer = 2 To grdAsgnTm.Rows.Count - 1
                          If grdAsgnTm.Rows.Item(i).Visible = False Then
                              If Val(DirectCast(grdAsgnTm.Rows.Item(i).Cells(2).Controls(0), TextBox).Text) > 0 Or Val(DirectCast(grdAsgnTm.Rows.Item(i).Cells(3).Controls(0), TextBox).Text) > 0 Then
                                  grdTmData += grdAsgnTm.Rows.Item(i).Cells(0).Text & ","
                                  grdTmData += grdAsgnTm.Rows.Item(i).Cells(1).Text & ","
                                  grdTmData += DirectCast(grdAsgnTm.Rows.Item(i).Cells(2).Controls(0), TextBox).Text & ","
                                  grdTmData += DirectCast(grdAsgnTm.Rows.Item(i).Cells(3).Controls(0), TextBox).Text & "|"
                              End If
                          End If
                      Next
                      Session("grdAsgnTmData") = grdTmData
                      Response.Redirect("ProjectNewAsgnMmbr.aspx")
                  End Sub
              Last edited by Frinavale; Nov 10 '09, 08:09 PM. Reason: Please post code in [code] ... [/code] tags. Added code tags.

              Comment

              • Frinavale
                Recognized Expert Expert
                • Oct 2006
                • 9749

                #8
                It is a lot more difficult to do this dynamically.
                If you don't have to use dynamic controls then you should avoid doing so if you're new to this...

                Of course, it is possible to dynamically create columns for your GridView. You should still use TemplteFields for this purpose for a bunch of reasons that I will address in a minute...but instead of declaratively defining them (in the ASPX page) you'll do so dynamically.

                Every control that you dynamically create will have to be instantiated during the Page Init event.

                The reason for this is because right after the Page Init event ViewState is loaded for all of the controls that the page uses. The ViewState contains state information for the control...

                For example, if you have a TextBox on the page, the TextBox is instantiated in the Page Init event and right after this the TextBox's ViewState is loaded which contains the text that the user entered. Now you're able to access the TextBox.Text property to retrieve the text entered by the user.

                The ViewState also contains event information. If your control was a button and the user clicked the button, the Click Event for the button is created when the ViewState for the button is loaded.

                If the button was not instantiated during the Page Init event, then the Button Click Event would not be loaded and your code won't be executed.

                I hope this makes my point.

                So, in your case you will have to create the columns for the GridView in the Page Init event. That way the ViewState information for the columns can be loaded and you can get the text the user entered, and handle any events that the columns may have raised.


                Now back to theTemplateFiel d.

                The reason why I am recommending that you use the TemplateField is because they exist so that you achieve what you want to achieve.

                These controls are data-bound and let you customize how the data that they're bound to is displayed and interacted with. Another important aspect to these controls is that they use the INamingContaine r interface. This interface makes sure that each dynamic control within the TemplateField (like your TextBoxes) have unique IDs etc. This lets you use the FindControl() method to retrieve the dynamic TextBoxes in the columns so that you can get the text that the user entered (right now, with your solution, you can't do this).....It takes a lot of work out of re-inventing the wheel.

                So, if you Really want to dynamically add columns to your GridView I can help you through it but you should first familiarize yourself with how to use dynamic controls in ASP.NET, the INamingContaine r Interface and also the ITemplate Interface because you need to have a very firm understanding of all of these topics before you start down this road.

                I still think that you should avoid dynamically creating the columns for the GridView. From past experience I can tell you that it can quickly become very tricky to maintain this, even when you know what you're doing.

                **edit**
                After that whole huge post it occurred to me that you may not realize the Data that is displayed in the GridView can be dynamically created very easily....but the columns (the structure/layout) for the GridView are very hard to dynamically create.

                Typically overall structure/layout of the GridView doesn't change. You know that you what columns you want to display, and what controls should be used to display the data in the columns. Therefore, there usually is no need to dynamically define the GridView's columns.

                It is the data that is displayed in the GridView that is dynamic.

                **close edit**


                -Frinny

                Comment

                • JohnShell
                  New Member
                  • Nov 2009
                  • 5

                  #9
                  Gridview

                  Frinny,

                  Impressive! Thank you very much for the information; for taking the time to reply; for taking the time to post such a concise and thorough explanation; and, for sharing your time, resources, and knowledge. Your actions are very much appreciated.

                  I am aware of the difficulties of programming dynamically. That approach is the preferred method in this particular shop. I am a neophyte with ASP.NET / VB.NET but, I am not new to programming. The dynamic approach will quickly be mastered and solely employed. Your information is very, very helpful.

                  Sincerely,

                  John

                  Comment

                  • Frinavale
                    Recognized Expert Expert
                    • Oct 2006
                    • 9749

                    #10
                    It's too bad that your style is like this.

                    There is a great benefit to keeping the page design separate from the logic separate from the back end. (I am a huge fan of the Model - View - Controller concept).

                    But since you need to do this dynamically, let's get to it!

                    The first thing I suggest is to implement a class that you can use as your Template.

                    The class will implement the ITemplate interface (that I touched on briefly earlier) and will specify how the column look.

                    Check out the link for the ITemplate Interface because I think it has a good example on how to implement it. Should get you going in the right direction :)

                    -Frinny

                    Comment

                    Working...