Gridview row editing - dynamic binding to a DropDo

2019-01-08 20:45发布

I'm trying to get an ASP.NET 3.5 GridView to show a selected value as string when being displayed, and to show a DropDownList to allow me to pick a value from a given list of options when being edited. Seems simple enough?

My gridview looks like this (simplified):

<asp:GridView ID="grvSecondaryLocations" runat="server" 
              DataKeyNames="ID" OnInit="grvSecondaryLocations_Init" 
              OnRowCommand="grvSecondaryLocations_RowCommand" 
              OnRowCancelingEdit="grvSecondaryLocations_RowCancelingEdit"
              OnRowDeleting="grvSecondaryLocations_RowDeleting"
              OnRowEditing="grvSecondaryLocations_RowEditing" 
              OnRowUpdating="grvSecondaryLocations_RowUpdating"  >
<Columns>
    <asp:TemplateField>
         <ItemTemplate>
              <asp:Label ID="lblPbxTypeCaption" runat="server" 
                                 Text='<%# Eval("PBXTypeCaptionValue") %>' />
         </ItemTemplate>
         <EditItemTemplate>
                      <asp:DropDownList ID="ddlPBXTypeNS" runat="server" 
                               Width="200px" 
                               DataTextField="CaptionValue" 
                               DataValueField="OID" />
         </EditItemTemplate>
    </asp:TemplateField>
</asp:GridView>

The grid gets displayed OK when not in editing mode - the selected PBX type shows its value in the asp:Label control. No surprise there.

I load the list of values for the DropDownList into a local member called _pbxTypes in the OnLoad event of the form. I verified this - it works, the values are there.

Now my challenge is: when the grid goes into editing mode for a particular row, I need to bind the list of PBX's stored in _pbxTypes.

Simple enough, I thought - just grab the drop down list object in the RowEditing event and attach the list:

protected void grvSecondaryLocations_RowEditing(object sender, GridViewEditEventArgs e)
{
    grvSecondaryLocations.EditIndex = e.NewEditIndex;

    GridViewRow editingRow = grvSecondaryLocations.Rows[e.NewEditIndex];

    DropDownList ddlPbx = (editingRow.FindControl("ddlPBXTypeNS") as DropDownList);
    if (ddlPbx != null)
    {
        ddlPbx.DataSource = _pbxTypes;
        ddlPbx.DataBind();
    }

    .... (more stuff)
}

Trouble is - I never get anything back from the FindControl call - seems like the ddlPBXTypeNS doesn't exist (or can't be found).

What am I missing?? Must be something really stupid.... but so far, all my Googling, reading up on GridView controls, and asking buddies hasn't helped.

Who can spot the missing link? ;-)

6条回答
老娘就宠你
2楼-- · 2019-01-08 20:54

You can use SelectedValue:

<EditItemTemplate>
    <asp:DropDownList ID="ddlPBXTypeNS"
                      runat="server"
                      Width="200px"
                      DataSourceID="YDS"
                      DataTextField="CaptionValue"
                      DataValueField="OID"
                      SelectedValue='<%# Bind("YourForeignKey") %>' />
    <asp:YourDataSource ID="YDS" ...../>
</EditItemTemplate>
查看更多
Bombasti
3楼-- · 2019-01-08 20:58

I am using a ListView instead of a GridView in 3.5. When the user wants to edit I have set the selected item of the dropdown to the exising value of that column for the record. I am able to access the dropdown in the ItemDataBound event. Here's the code:

protected void listViewABC_ItemDataBound(object sender, ListViewItemEventArgs e)
{
    // This stmt is used to execute the code only in case of edit 
    if (((ListView)(sender)).EditIndex != -1 && ((ListViewDataItem)(e.Item)).DisplayIndex == ((ListView)(sender)).EditIndex)
    {
        ((DropDownList)(e.Item.FindControl("ddlXType"))).SelectedValue = ((MyClass)((ListViewDataItem)e.Item).DataItem).XTypeId.ToString();
        ((DropDownList)(e.Item.FindControl("ddlIType"))).SelectedValue = ((MyClass)((ListViewDataItem)e.Item).DataItem).ITypeId.ToString();
    }
}
查看更多
迷人小祖宗
4楼-- · 2019-01-08 20:59
 <asp:GridView ID="GridView1" runat="server" PageSize="2" AutoGenerateColumns="false"
            AllowPaging="true" BackColor="White" BorderColor="#CC9966" BorderStyle="None"
            BorderWidth="1px" CellPadding="4" OnRowEditing="GridView1_RowEditing" OnRowUpdating="GridView1_RowUpdating"
            OnPageIndexChanging="GridView1_PageIndexChanging" OnRowCancelingEdit="GridView1_RowCancelingEdit"
            OnRowDeleting="GridView1_RowDeleting">
            <FooterStyle BackColor="#FFFFCC" ForeColor="#330099" />
            <RowStyle BackColor="White" ForeColor="#330099" />
            <SelectedRowStyle BackColor="#FFCC66" Font-Bold="True" ForeColor="#663399" />
            <PagerStyle BackColor="#FFFFCC" ForeColor="#330099" HorizontalAlign="Center" />
            <HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="#FFFFCC" />
            <Columns>
            <asp:TemplateField HeaderText="SerialNo">
            <ItemTemplate>
            <%# Container .DataItemIndex+1 %>.&nbsp
            </ItemTemplate>
            </asp:TemplateField>
                <asp:TemplateField HeaderText="RollNo">
                    <ItemTemplate>
                        <%--<asp:Label ID="lblrollno" runat="server" Text='<%#Eval ("RollNo")%>'></asp:Label>--%>
                        <asp:TextBox ID="txtrollno" runat="server" Text='<%#Eval ("RollNo")%>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="SName">
                    <ItemTemplate>
                    <%--<asp:Label ID="lblsname" runat="server" Text='<%#Eval("SName")%>'></asp:Label>--%>
                        <asp:TextBox ID="txtsname" runat="server" Text='<%#Eval("SName")%>'> </asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="C">
                    <ItemTemplate>
                    <%-- <asp:Label ID="lblc" runat="server" Text='<%#Eval ("C") %>'></asp:Label>--%>
                        <asp:TextBox ID="txtc" runat="server" Text='<%#Eval ("C") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Cpp">
                    <ItemTemplate>
                    <%-- <asp:Label ID="lblcpp" runat="server" Text='<%#Eval ("Cpp")%>'></asp:Label>--%>
                       <asp:TextBox ID="txtcpp" runat="server" Text='<%#Eval ("Cpp")%>'> </asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Java">
                    <ItemTemplate>
                       <%--  <asp:Label ID="lbljava" runat="server" Text='<%#Eval ("Java")%>'> </asp:Label>--%>
                        <asp:TextBox ID="txtjava" runat="server" Text='<%#Eval ("Java")%>'> </asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Edit" ShowHeader="False">
                    <EditItemTemplate>
                        <asp:LinkButton ID="lnkbtnUpdate" runat="server" CausesValidation="true" Text="Update"
                            CommandName="Update"></asp:LinkButton>
                        <asp:LinkButton ID="lnkbtnCancel" runat="server" CausesValidation="false" Text="Cancel"
                            CommandName="Cancel"></asp:LinkButton>
                    </EditItemTemplate>
                    <ItemTemplate>
                        <asp:LinkButton ID="btnEdit" runat="server" CausesValidation="false" CommandName="Edit"
                            Text="Edit"></asp:LinkButton>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:CommandField HeaderText="Delete" ShowDeleteButton="True" ShowHeader="True" />
                <asp:CommandField HeaderText="Select" ShowSelectButton="True" ShowHeader="True" />
            </Columns>
        </asp:GridView>
        <table>
            <tr>
                <td>
                    <asp:Label ID="lblrollno" runat="server" Text="RollNo"></asp:Label>
                    <asp:TextBox ID="txtrollno" runat="server"></asp:TextBox>
                </td>
                <td>
                    <asp:Label ID="lblsname" runat="server" Text="SName"></asp:Label>
                    <asp:TextBox ID="txtsname" runat="server"></asp:TextBox>
                </td>
                <td>
                    <asp:Label ID="lblc" runat="server" Text="C"></asp:Label>
                    <asp:TextBox ID="txtc" runat="server"></asp:TextBox>
                </td>
                <td>
                    <asp:Label ID="lblcpp" runat="server" Text="Cpp"></asp:Label>
                    <asp:TextBox ID="txtcpp" runat="server"></asp:TextBox>
                </td>
                <td>
                    <asp:Label ID="lbljava" runat="server" Text="Java"></asp:Label>
                    <asp:TextBox ID="txtjava" runat="server"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td>
                    <asp:Button ID="Submit" runat="server" Text="Submit" OnClick="Submit_Click" />
                    <asp:Button ID="Reset" runat="server" Text="Reset" OnClick="Reset_Click" />
                </td>
            </tr>
        </table>
查看更多
混吃等死
5楼-- · 2019-01-08 21:04

Quite easy... You're doing it wrong, because by that event the control is not there:

protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow && 
        (e.Row.RowState & DataControlRowState.Edit) == DataControlRowState.Edit)
    { 
        // Here you will get the Control you need like:
        DropDownList dl = (DropDownList)e.Row.FindControl("ddlPBXTypeNS");
    }
}

That is, it will only be valid for a DataRow (the actually row with data), and if it's in Edit mode... because you only edit one row at a time. The e.Row.FindControl("ddlPBXTypeNS") will only find the control that you want.

查看更多
看我几分像从前
6楼-- · 2019-01-08 21:07
protected void grvSecondaryLocations_RowEditing(object sender, GridViewEditEventArgs e)  
{  
    grvSecondaryLocations.EditIndex = e.NewEditIndex;  

    DropDownList ddlPbx = (DropDownList)(grvSecondaryLocations.Rows[grvSecondaryLocations.EditIndex].FindControl("ddlPBXTypeNS"));
    if (ddlPbx != null)  
    {  
        ddlPbx.DataSource = _pbxTypes;  
        ddlPbx.DataBind();  
    }  

    .... (more stuff)  
}
查看更多
淡お忘
7楼-- · 2019-01-08 21:10

The checked answer from balexandre works great. But, it will create a problem if adapted to some other situations.

I used it to change the value of two label controls - lblEditModifiedBy and lblEditModifiedOn - when I was editing a row, so that the correct ModifiedBy and ModifiedOn would be saved to the db on 'Update'.

When I clicked the 'Update' button, in the RowUpdating event it showed the new values I entered in the OldValues list. I needed the true "old values" as Original_ values when updating the database. (There's an ObjectDataSource attached to the GridView.)

The fix to this is using balexandre's code, but in a modified form in the gv_DataBound event:

protected void gv_DataBound(object sender, EventArgs e)
{
    foreach (GridViewRow gvr in gv.Rows)
    {
        if (gvr.RowType == DataControlRowType.DataRow && (gvr.RowState & DataControlRowState.Edit) == DataControlRowState.Edit)
        {
            // Here you will get the Control you need like:
            ((Label)gvr.FindControl("lblEditModifiedBy")).Text = Page.User.Identity.Name;
            ((Label)gvr.FindControl("lblEditModifiedOn")).Text = DateTime.Now.ToString();
        }
    }
}
查看更多
登录 后发表回答