ASPxGridView多页场景下ASPxCheckBox引发对象引用未设置实例错误
ASPxGridView分页下遍历模板控件触发空引用错误的原因分析
问题场景
- 使用DevExpress ASPxGridView控件,在列模板中嵌入ASPxCheckBox
- 分页大小设置为20行,当数据总条数超过20条(存在多页)时,点击
btnTransferAsset按钮执行遍历逻辑,循环到第21行时出现Object reference not set to an instance of an object错误
页面标记代码
<dx:ASPxGridView ID="grdAsset" runat="server" Width="100%" AutoGenerateColumns="true" Caption="Assets List" KeyFieldName="id" DataSourceID="getAssets"> <Columns> <dx:GridViewDataColumn Caption="" FieldName="id" VisibleIndex="0" Visible="false" ReadOnly="true" /> <dx:GridViewDataButtonEditColumn Caption="#" VisibleIndex="1" Width="50px"> <DataItemTemplate> <dx:ASPxCheckBox ID="chkID" runat="server" /> </DataItemTemplate> </dx:GridViewDataButtonEditColumn> <dx:GridViewDataColumn Caption="" FieldName="asset_id" VisibleIndex="2" /> <dx:GridViewDataColumn Caption="Asset Category" FieldName="category_name" VisibleIndex="3" /> <dx:GridViewDataColumn Caption="Asset Brand Name" FieldName="brand_name" VisibleIndex="4" /> 'others Datacolumn..... </Columns> <SettingsBehavior AllowSelectByRowClick="true" ColumnResizeMode="Control" /> <SettingsPager Position="Bottom" PageSize="20"> <PageSizeItemSettings Items="10, 20, 50, 100, 200, 500" ShowAllItem="True" Visible="True" /> </SettingsPager> <Settings ShowFilterRow="true" ShowFooter="true" /> <SettingsDataSecurity AllowDelete="False" AllowEdit="False" AllowInsert="False" /> <Settings GridLines="Horizontal" /> <Styles> <AlternatingRow Enabled="True" /> </Styles> </dx:ASPxGridView> <asp:ObjectDataSource ID="getAssets" runat="server" TypeName="Asset" SelectMethod="selectAsset"> <SelectParameters> 'the parameters... </SelectParameters> </asp:ObjectDataSource> <br/> <dx:ASPxButton ID="btnTransferAsset" runat="server" Text="Transfer Assets" Font-Bold="true" Visible="false" OnClick="btnTransferAsset_Click" />
后台代码
Private Sub btnTransferAsset_Click (sender As Object, e As EventArgs) Dim dt As New DataTable dt.Columns.AddRange(New DataColumn(2) {New DataColumn("id"), New DataColumn("asset_id"), New DataColumn("category_name")}) For rowIndex As Integer = 0 To grdAsset.VisibleRowCount - 1 Dim column As GridViewDataButtonEditColumn = CType(grdAsset.Columns(1), GridViewDataButtonEditColumn) Dim cb As ASPxCheckBox = CType(grdAsset.FindRowCellTemplateControl(rowIndex, column, "chkID"), ASPxCheckBox) If cb.Checked Then 'got error here, at the loop 21 times, it shows "Object reference not set to an instance of an object." Dim id As Integer = CType(grdAsset.GetRowValues(rowIndex, New String() {"id"}), Integer) Dim asset_id As String = CType(grdAsset.GetRowValues(rowIndex, New String() {"asset_id"}), String) Dim category_name As String = CType(grdAsset.GetRowValues(rowIndex, New String() {"category_name"}), String) dt.Rows.Add(id, asset_id, category_name) End If Next 'my others code... End Sub
错误原因
核心原因是ASPxGridView在分页模式下,仅当前页的行对应的模板控件会被渲染到服务器端控件树中,非当前页的行并没有生成对应的ASPxCheckBox控件实例。
代码中grdAsset.VisibleRowCount返回的是所有数据的总行数(比如21条),但循环到第21行(对应第二页的第一行)时,FindRowCellTemplateControl找不到该页面对应的chkID控件,返回Nothing,此时直接访问cb.Checked就会触发空引用错误。
另外需要注意:grdAsset.GetRowValues可以获取到所有行的数据,是因为这个方法直接从GridView绑定的数据源(或控件内部缓存的全量数据)中读取,不需要依赖页面上已渲染的控件,所以即使行不在当前页也能正常取值,但模板控件只存在于当前页。
内容的提问来源于stack exchange,提问作者Newbie
相关产品推荐
相关产品推荐

