Search code examples
c#asp.netgridviewedititemtemplate

DropDownList in EditIemTemplate does not update table


So I have a GridView that display loaning information, my Loans table has the ID for Laptop, User, Location, etc.

When I display on the GridView, instead I use names instead of ID numbers.

My problem is when I put a dropdownlist in the edititemtemplate such as below it does not update my table and I get the below error I want to be able to update my loans table with the appropriate info:

Cannot insert the value NULL into column 'Laptop_ID', table 'itassetmgmt.dbo.Loans'; column does not allow nulls. UPDATE fails. The statement has been terminated.

Loans Table include: Loan_ID Date_Loaned Date_Returned Sign_Off Laptop_ID User_ID Dept_ID Location_ID

ASPX:

<asp:TemplateField HeaderText="Laptop_Name" SortExpression="Laptop_Name">
            <EditItemTemplate>
                <asp:DropDownList ID="DropDownList1" SelectedValue ='<%# Bind("Laptop_Name") %>' runat="server" DataSourceID="editLPID" DataTextField="Laptop_Name" DataValueField="Laptop_Name">
                </asp:DropDownList>
                <asp:SqlDataSource ID="editLPID" runat="server" ConnectionString="<%$ ConnectionStrings:itassetmgmtConnectionString1 %>" SelectCommand="SELECT [Laptop_ID], [Laptop_Name] FROM [Laptops]"></asp:SqlDataSource>
            </EditItemTemplate>
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server" Text='<%# Bind("Laptop_Name") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Name" SortExpression="Name">
            <EditItemTemplate>
                <asp:DropDownList ID="DropDownList2" runat="server" SelectedValue='<%# Bind("Name") %>' DataSourceID="editUID" DataTextField="Name" DataValueField="Name">
                </asp:DropDownList>
                <asp:SqlDataSource ID="editUID" runat="server" ConnectionString="<%$ ConnectionStrings:itassetmgmtConnectionString1 %>" SelectCommand="SELECT User_ID, Firstname +' '+ Lastname AS Name FROM Users"></asp:SqlDataSource>
            </EditItemTemplate>
            <ItemTemplate>
                <asp:Label ID="Label2" runat="server" Text='<%# Bind("Name") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Department" SortExpression="Department">
            <EditItemTemplate>
                <asp:DropDownList ID="DropDownList3" runat="server" SelectedValue='<%# Bind("Department") %>' DataSourceID="editDID" DataTextField="Department" DataValueField="Department">
                </asp:DropDownList>
                <asp:SqlDataSource ID="editDID" runat="server" ConnectionString="<%$ ConnectionStrings:itassetmgmtConnectionString1 %>" SelectCommand="SELECT * FROM [Departments]"></asp:SqlDataSource>
            </EditItemTemplate>
            <ItemTemplate>
                <asp:Label ID="Label3" runat="server" Text='<%# Bind("Department") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Location_Name" SortExpression="Location_Name">
            <EditItemTemplate>
                <asp:DropDownList ID="DropDownList4" runat="server" SelectedValue='<%# Bind("Location_Name") %>' DataSourceID="editLID" DataTextField="Location_Name" DataValueField="Location_Name">
                </asp:DropDownList>
                <asp:SqlDataSource ID="editLID" runat="server" ConnectionString="<%$ ConnectionStrings:itassetmgmtConnectionString1 %>" SelectCommand="SELECT * FROM [Locations]"></asp:SqlDataSource>
            </EditItemTemplate>
            <ItemTemplate>
                <asp:Label ID="Label4" runat="server" Text='<%# Bind("Location_Name") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>

EDIT: I know that it's probably because the DataValueField for the DropDownList isn't set to the corresponding ID# in the table, but when I change the DataValueField, it gives me a bunch of errors. Any suggestions?

My Update Command: UpdateCommand="UPDATE [Loans] SET [Date_Loaned] = @Date_Loaned, [Date_Returned] = @Date_Returned, [Sign_Off] = @Sign_Off, [Laptop_ID] = @Laptop_ID, [User_ID] = @User_ID, [Dept_ID] = @Dept_ID, [Location_ID] = @Location_ID WHERE [Loan_ID] = @original_Loan_ID"


Solution

  • In the Gridview take out all ID's from the displayable portion of the grid. No need to display them, however they must be part of the gridview datasource in order to bind against them

    Then in the ItemTemplate (I'm only showing the user template) DataTextField and DataValueField come from the DropDownList datasource BUT the SelectedValue property is bound against the Gridview User_ID :

    <asp:TemplateField>
      <ItemTemplate>
        <asp:DropDownList ID="DropDownList2Disabled" runat="server" DataSourceID="SqlDataSource3"
          Enabled="False" 
          DataTextField="Name" 
          DataValueField="User_ID" 
          SelectedValue='<%# Eval("User_ID") %>'>
        </asp:DropDownList>
      </ItemTemplate>
      <EditItemTemplate>
        <asp:DropDownList ID="DropDownList2" runat="server" DataSourceID="SqlDataSource3"
          DataTextField="Name" 
          DataValueField="User_ID" 
          SelectedValue='<%# Bind("User_ID") %>'>
        </asp:DropDownList>
      </EditItemTemplate>
    </asp:TemplateField>
    

    I'm using a DDL in both the ItemTemplate and EditItemTemplate, disabled in one and enabled in the other. you can use a label if you wish in the item table but that would require a bit more work as the username is not part of the gridview.

    If you have control of the gridview sql and can add the username to the dataset (say as UserName) then you could bind an ItemTemplate label to the UserName and the EditItemTemplate DropDownList to the User_ID

    EDIT: Expanded Example:

    So, Going with the Label idea the template would look something like this:

    <asp:TemplateField>
      <ItemTemplate>
        <asp:Label ID="LabelUserName" runat="server" Text='<%# Eval("UserName") %>'>
        </asp:Label>
      </ItemTemplate>
      <EditItemTemplate>
        <asp:DropDownList ID="DropDownList2" runat="server" DataSourceID="SqlDataSource3"
          DataTextField="Name" 
          DataValueField="User_ID" 
          SelectedValue='<%# Bind("User_ID") %>'>
        </asp:DropDownList>
      </EditItemTemplate>
    </asp:TemplateField>
    

    And the Gridview DataSource Select(or Stored Proc) would look (or contain) something like this:

    Select Loan_ID 
        ,  l.Date_Loaned 
        ,  l.Date_Returned 
        ,  l.Sign_Off 
        ,  l.Laptop_ID 
        ,  l.User_ID 
        ,  u.FirstName + ' ' + u.LastName as UserName 
        ,  l.Dept_ID
        ,  d.DepartmentName
        ,  l.Location_ID
        ,  (etc...)
        From LoansTable l
            Left Join UserTable u on u.User_ID = l.User_ID
            Left Join DeptTable d on d.Dept_ID = l.Dept_ID
            (etc.)
        Order By d.DepartmentName
            ,    l.Date_Loaned
    

    So this would return a fieldset that provides the Gridview with enough User Friendly Data for a clean display and also the ID's that you, the programmer, may require to make changes as the user interacts with the Gridview.

    Now the ID's may or may not be added to the GridView by adding them to the DataKeyNames property. This would allow for easy access to the ID's in the code behind during GridView Postbacks. Keys placed here are not part of the displayable portion of the GridView

    The DDL in the EditItemTemplate has it's own DataSource and has a simple Select:

    Select User_ID, FirstName + ' ' + LastName as Name From UserTable
    

    Do not confuse duplicate Fields from 2 different DataSources. In the EditItemTemplate the DDL Declaration:

    <asp:DropDownList ID="DropDownList2" runat="server" DataSourceID="SqlDataSource3"
        DataTextField="Name" 
        DataValueField="User_ID" 
        SelectedValue='<%# Bind("User_ID") %>'>
    </asp:DropDownList>
    

    DataValueField="User_ID" refers to the DDL DataSource whereas SelectedValue='<%# Bind("User_ID") %>' is a Binding to the User_ID field in the GridView DataSource

    Here the Gridview User_ID field is "hidden" from the user but available to the Gridview for editing purposes and conditionally available to you programmatically if you placed it in DataKeyNames