Why is My GridView FooterRow Referencing the Wrong Row?

扶醉桌前 提交于 2019-12-11 05:47:09

问题


I have a GridView and, using a fairly common method, I'm using a FooterRow and TemplateFields to provide the missing insert ability. So far so good.

The footer contains a TemplateField with a LinkButton to provide the postback that does the insertion. In the handler for the LinkButton's click, the Insert() method is called on the ObjectDataSource that the GridView is bound to. The ObjectDataSource's insert parameters are populated in the handler for its Inserting event. The code for all of this (abridged) looks like this:

Markup:

<asp:GridView ID="gvComplexRates" runat="server" AutoGenerateColumns="False" 
                DataKeyNames="id" DataSourceID="odsComplexMileageRates" 
                EnableModelValidation="True" ShowFooter="True">
                <Columns>
                   <asp:TemplateField ShowHeader="False">
                        :
                        :
                        <FooterTemplate>
                            <asp:LinkButton ID="addLinkButton" runat="server" CausesValidation="false"
                                CommandName="Insert" Text="Add"></asp:LinkButton>
                        </FooterTemplate>
                    </asp:TemplateField>
                    :
                    :
</asp:GridView>

Code Behind:

Private Sub gvComplexRates_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles gvComplexRates.RowCommand

    Select Case e.CommandName
        Case "Insert"
            odsComplexMileageRates.Insert()
    End Select
End Sub

Private Sub odsComplexMileageRates_Inserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ObjectDataSourceMethodEventArgs) Handles odsComplexMileageRates.Inserting
    Dim fuelTypeDropDown As DropDownList = gvComplexRates.FooterRow.FindControl("ddFuelTypeInsert")
    Dim engineTypeDropDown As DropDownList = gvComplexRates.FooterRow.FindControl("ddEngineTypeInsert")
    Dim rateTextBox As TextBox = gvComplexRates.FooterRow.FindControl("tbRateInsert")
    Dim vatRateTextBox As TextBox = gvComplexRates.FooterRow.FindControl("tbVatRateInsert")

    e.InputParameters("expense_type_id") = ddExpenseTypeSelect.SelectedValue
    e.InputParameters("fuel_type_id") = fuelTypeDropDown.SelectedValue
    e.InputParameters("engine_type_id") = engineTypeDropDown.SelectedValue
    e.InputParameters("rate") = rateTextBox.Text
    e.InputParameters("vat_rate") = vatRateTextBox.Text
End Sub

Two of the fields in my FooterRow are DropDownLists that are populated from other tables. Again this works fine and I can add, edit and remove rows without problem.

The problem comes when I use a modal dialog from this page to insert extra rows into the tables used to populate the DropDownLists in the FooterRow. The insert operations work fine and the modal dialog closes and at this point I use a javascript postback (basically a call to __doPostBack()) so that my FooterRow DropDownLists can be updated. The code for this is:

Protected Sub updateFuelEngineDropdowns()
    odsFuelTypes.Select()
    odsEngineTypes.Select()
    Dim dropDown As DropDownList = gvComplexRates.FooterRow.FindControl("ddFuelTypeInsert")
    dropDown.DataBind()
    dropDown = gvComplexRates.FooterRow.FindControl("ddEngineTypeInsert")
    dropDown.DataBind()
End Sub

This sub, updateFuelEngineDropdowns(), is called from the Page Load event. The first time I called it it worked fine. For some reason in subsequent runs through the debugger I'm getting NullReferenceExceptions. Digging into the debug object viewer it is apparent that the GridView FooterRow is referencing the row above the footer which contains no controls (at least not at this non-editing stage) and so, quite reasonably, gives my the Null reference.

The debug QuickView expressions I use are:
gvComplexRates.FooterRow.Controls(3) DirectCast(gvComplexRates.FooterRow.Controls(3),System.Web.UI.WebControls.DataControlFieldCell).Controls(1)

The first of these shows a tag of td. Which makes sense. The second shows text of "10" which is the content for the row above the footer.

Does anybody know why this is happening?

Thanks Dan


回答1:


Where are you "providing the missing insert ability"? You have to rebuild the footer-controls on every postback, the GridView.RowCreated-Event would be a good place.

Update: You have to Databind your GridView after you inserted new rows into your Dropdowns' Tables.




回答2:


Right, this is a bit embarrassing. I gave a little white lie in the original question. By omission rather than a deliberate attempt to mislead. I am not, in fact, using a GridView but a subclass of it that will display rows when the datasource contains no data. This enables the user to insert new rows when the table is empty. This subclass overrides the FooterRow property and, to my shame, it was this that was getting things wrong. So I made two errors here: first I failed to test my GridView subclass properly and second I sought to prevent what I thought would be unnecessary attention on my subclass by not showing its use in the code snippets I included in the question. My bad. Thanks to Tim for taking the time to try and help me.

Dan



来源:https://stackoverflow.com/questions/3574196/why-is-my-gridview-footerrow-referencing-the-wrong-row

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!