`

常见 Datagrid 错误

阅读更多
Marcie Robillard
DatagridGirl.com

Datagrid 控件是 Microsoft® ASP.NET 中功能最强、用途最广的 Web 控件之一,这一点已经得到了 ASP.NET 权威人士的认同。虽然 Datagrid 控件易于使用,但同样易于给使用者带来麻烦。以下是许多人所犯的一些错误,这些人包括从初学者到富有经验的 .NET 专家。您可以看到许多苦闷的使用者在 ASP.NET 新闻组和论坛就这些错误提出问题。遵循本文概述的相当简单的步骤,可以帮助您避免这些错误,并节约大量的开发时间。

可以使用 Datagrid 创建列表数据而没有使用

我知道您不会再使用如下所示的代码,但 ASP.NET 领域中许多守旧的用户仍在继续使用它们:

Response.Write("<table>")
While MyDataReader.Read()
Response.Write("<tr>")
Response.Write("<td>")
Response.Write(MyDataReader(0))
Response.Write("</td>")
Response.Write("</tr>")
Loop
Response.Write("</table>")

可以对以上代码进行简化,使其仅为:

<asp:datagrid runat="server" datasource="MyDataReader"/>,并调用 .DataBind() 方法。即使需要对 HTML 输出进行特殊的控制,您也可以在用户界面上记录集的内容重复出现的情况下,使用某个数据 Web 控件。

忘记在 Page_Load 事件中检查 IsPostBack

最常见的错误之一是忘记在数据绑定之前检查页面的 IsPostBack 条件。例如,Datagrid 处于“Edit”(编辑)模式时,忽略该项检查将导致已编辑的值被数据源中的原始值覆盖。然而,该规则至少有一个主要的例外,请参阅持续使用大型 ViewState

以下是包含 IsPostBack 检查的一个典型 Page_Load 事件。BindGrid() 是一个例程,用于导入并设置 Datagrid 的数据源,并调用 DataBind() 方法。

Sub Page_Load
  If Not IsPostBack Then 
    BindGrid()
  End If
End Sub

需要更大的灵活性时,仍坚持使用自动生成的列

如果 Datagrid 所处的环境需要任何一种特殊格式,或是需要使用 Datagrid 中的其他任何 Web 控件,那么必须关闭 AutoGenerateColumns。将 AutoGenerateColumns 属性的设置保持为“True”(默认设置)的做法,仅在最简单的 Datagrid 方案中有效。但对几乎所有实际的应用程序,必须将该属性设置为“False”,并在 Datagrid 声明的 <columns></columns> 段中明确地指定列。Microsoft Visual Studio® .NET 用户可以使用属性生成器以图形化的方式创建这些列。

注意:如果将 AutoGenerateColumns 的设置保持为“True”,并且在 Datagrid 的 <columns> 段中指定了列,那么最终将得到对列的重复设置。系统将首先显示特别声明的列,随后是所有自动生成的列。

尝试仅使用控件 ID 来引用 Datagrid 项目中的控件

许多人没有认识到,对于 Datagrid 的 TemplateColumn 下的 ItemTemplate 中的控件(例如带有“MyTextBox”ID 的 TextBox 控件),不能在后面的代码或是在 ASPX 页面的 <script> 段中用如下所示的代码来直接调用该控件:

Dim MyValue As String = MyTextBox.Text

该代码将导致可怕的“名称‘MyTextBox’没有声明”错误。

因为 Datagrid 是由多个行(项目)组成的,所以数据源中的每一行实际都会有一个单独的“MyTextBox”实例。ASP.NET 在每个控件的 ID 前面加上该控件层次结构中每个命名容器的 ID,这样 Textbox 将具有唯一的 ID,与页面中所有其他控件的 ID 都不相同。例如,如果 MyTextBox 处于 DataGrid1 中,那么生成的 ID 将是 DataGrid1:_ctl2:MyTextBox。“_ctl2”代表 MyTextBox 所处的当前行。页面中其他 MyTextBox 实例的 ID 可能是 DataGrid1:_ctl3:MyTextBox、DataGrid1:_ctl4:MyTextBox 等等。要检索需要查找的“MyTextBox”值,需要对适当的 DataGridItem 调用 FindControl 方法。该 DataGridItem 用作 TextBox 的父命名容器。

HTML:

<asp:Datagrid runat="server" id="Datagrid1">
<Columns>
<asp:TemplateColumn>
<ItemTemplate>
<asp:TextBox runat="server" id="MyTextBox"/>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>

代码:

Sub DataGrid1_UpdateCommand(sender As Object, _
    e As DataGridCommandEventArgs)
  Dim MyValue As String = _
    CType(e.Item.FindControl("MyTextBox"), TextBox).Text
  '对 MyValue 执行操作
End Sub

对 FindControl 调用的结果调用 CType,将会把返回值由 Object 类型强制转换成 TextBox 类型,以访问 .Text 属性。

可以(或应该)使用分页而没有使用

用户未必希望在单个页面上滚动查看成千上万条记录。请确保您的应用程序设计合理,能够处理可能会返回大量记录的情况。有关如何在 Datagrid 中实现分页的信息,请参阅 Paging in DataGrid QuickStart Tutorial。在 Scott Mitchell 的文章 Creating a Pageable, Sortable DataGrid 中可以找到更多的信息。

忘记在每个 Datagrid 事件中执行 .DataBind() 调用,从而导致回发

一个常见的问题是:“当我点击 Datagrid 某一行中的 Edit(编辑)链接时,页面回发,且不包含任何数据。这是什么错误?”问题在于数据仅在页面第一次被调用时绑定到网格。在每个 Datagrid 事件(Edit、Update、Cancel、PageSort)中,请确保设置了 Datagrid 的 Datasource 属性(除非已经在 <asp:Datagrid> 声明中通过声明的方式进行了设置),并对 Datagrid 调用了 DataBind() 方法。

运行时不必要地在 Datagrid 中动态创建 Datagrid 控件或列

在某些业务和技术方案中,在运行时创建 ASP.NET 控件是必要的,也是完全合适的。例如,有时需要在选择其他页面选项后,才能在运行时确定用户界面。或是要创建一个复合服务器控件,其中的每个子控件都需要动态创建,因为无法以声明的方式创建这些子控件。如果遇到这些情况,请注意,提交页面时不要保留这些动态控件。必须在页面生命周期的早期,在每次回发时重新创建动态控件(例如在 Page_Init 事件中)。警言:创建控件要早,创建控件要勤。有关如何动态创建控件的详细信息,请参阅 Microsoft Knowledge Base 文章 HOW TO:Dynamically Create Controls in ASP.NET with Visual Basic .NET

然而,如果 Datagrid 应用程序中不是一定需要动态创建控件,请避免使用该技术,以免遇到麻烦。尽管可能创建动态 Datagrid,但它们会引发各种事件,这通常都会令人头疼。换句话说,不要动态创建控件,以避免因为创建控件使 ASPX 文件变得散乱。

持续使用大型 ViewState

Datagrid 控件会在页面中添加大量的 ViewState,这一点令人讨厌,因为这会导致呈现给用户的页面的总体大小急剧增加。要使页面大小不增加,最简单的方法是无论对整个页面,还是单独对某些特定的控件,都禁用 ViewState。例如,如果页面不产生回发,那么对整个页面禁用 ViewState 是安全的。否则,请对两次回发之间状态信息不会发生更改的各个控件禁用 ViewState,或者对不需要隐藏字段来跟踪自身状态的那些控件禁用 ViewState。

对 Datagrid 控件或包含 Datagrid 的页面禁用 ViewState 时,如果 Datagrid 会启动回发事件,那么需要执行一些特殊的步骤。首先,必须在每次回发时在 Page_Load 中重新绑定 Datagrid。这有违常规做法(以及上述第二个问题中的描述)。但如果禁用 ViewState,该步骤是必需的,这样在执行 Page_Load 后可以正确地引发其他 Datagrid 事件。如果要处理以下 Datagrid 事件中的任何一部分(或全部),那么还需要在 ViewState 中手动存储一些 Datagrid 属性。例如,在禁用了 ViewState 的 Datagrid 中进行编辑时,只要是在 Page_Load 中第一次绑定 Datagrid 之前重新存储 EditItemIndex,且 Datagrid 处于编辑模式,那么只需将 EditItemIndex 储存到 ViewState 就够了(请参阅示例代码)。

表 1:Datagrid 事件与 ViewState 的依赖关系

事件 是否依赖于 ViewState? 要存储在 ViewState 中的字段
ItemCreated  
ItemDataBound  
SortCommand SortExpression
EditCommand EditItemIndex
PageIndexChanged CurrentPageIndex
SelectedIndexChanged  

清单 1:启用编辑、排序和分页,但禁用 ViewState 的 Datagrid 的示例代码。

Sub Page_Load
If Not ViewState("EditItemIndex") Is Nothing Then
    Datagrid1.EditItemIndex = ViewState("EditItemIndex")
  End If
  If Not ViewState("CurrentPageIndex") Is Nothing Then
    Datagrid1.CurrentPageIndex = ViewState("CurrentPageIndex")
  End If
  BindGrid()
End Sub

Sub BindGrid()
  Dim DV As DataView
  DV = GetDataSource()
  DV.Sort = ViewState("SortExpression")
  Datagrid1.DataSource = DV
  Datagrid1.DataBind()
End Sub

Sub Datagrid1_SortCommand(s As Object, _
    e As DataGridSortCommandEventArgs)
  ViewState("SortExpression") = e.SortExpression
  BindGrid()
End Sub

Sub Datagrid1_EditCommand(s As Object, _
    e As DatagridCommandEventArgs)
  Datagrid1.EditItemIndex = e.Item.ItemIndex
  ViewState("EditItemIndex") = e.Item.ItemIndex
  BindGrid()
End Sub

Sub Datagrid1_PageIndexChanged(s as Object, _
    e As DataGridPageChangedEventArgs)
  Datagrid1.CurrentPageIndex = e.NewPageIndex
  ViewState("CurrentPageIndex") = e.NewPageIndex
  BindGrid()
End Sub

使用 ItemDataBound 或 ItemCreated 事件时,忘记检查适当的 ListItemType

Datagrid 控件对每个数据行引发两个事件。首次将每行添加到 Datagrid 时将引发 ItemCreated 事件,将数据绑定到每行时将引发 ItemDataBound 事件。添加单元格到 Datagrid 的表格输出时,这些事件可以用于控制每个单元格的外观或内容。例如,可以基于数值的范围修改单元格的背景颜色。但关键是要记住,这些事件的引发针对的是所有 Datagrid 项目类型,包括页眉、页脚和分页程序项目。如果执行 ItemDataBound 事件期间,没有在引用项目的数据之前仔细检查项目类型,第一个项目(通常是标题行)就将发生错误。如果 Datagrid 启用了分页,且将其设置为在顶端显示,那么第一个项目就会成为分页程序项目。以下示例代码显示如何在引用项目数据之前进行正确的 ListItemType 检查。不要忘了 AlternatingItem!

Sub DataGrid1_ItemDataBound(source As Object, _
    e As DataGridItemEventArgs)
      If (e.Item.ItemType = ListItemType.Item Or _
    e.Item.ItemType = ListItemType.AlternatingItem) Then
        If e.Item.DataItem("ForumDate") < DateTime.Today Then 
          e.Item.Cells(1).BackColor = 
          System.Drawing.Color.FromName("#ffccff")
     End If
      End If
End Sub

需要对生成的 HTML 有更多的控制时,过多地使用了 Datagrid(Repeater 也许是更好的选择)

如果懒散的程序员喜欢 Datagrid 控件(因为 Datagrid 控件为他们完成了很多工作),那么有着极强控制欲的程序员必定喜欢 Repeater 控件。如果需要或希望完全控制创建的所有 HTML,请使用 Repeater 控件,它能帮助您完成该任务。Repeater 控件在性能上也略占优势,因为它不像 Datagrid 控件的所有内置功能那样占用系统资源。也可以考虑使用折衷的 DataList 控件,它具备编辑和排序功能,同时还具有在一行内重复显示记录的功能。

评论

相关推荐

    ASP.Net开发者常见 Datagrid 错误

    ASP.NET Datagrid 控件是开发Web应用程序时常用的数据展示组件,尤其在处理表格数据时...通过遵循这些最佳实践,ASP.NET开发者可以避免常见的Datagrid错误,提高代码质量,同时减少调试时间,使项目更加稳定和高效。

    ASP.NET中Datagrid常见错误

    ### ASP.NET中Datagrid常见错误解析 #### 一、概述 Datagrid 控件作为ASP.NET中最强大且用途广泛的Web控件之一,在实际开发过程中被广泛使用。然而,由于其复杂的功能性和灵活性,开发者在使用过程中很容易遇到...

    DataGrid 中加入图标

    DataGrid控件是许多编程语言和框架中的常见组件,用于在表格形式中显示和操作数据。在这个场景中,"DataGrid 中加入图标"是一个重要的知识点,它涉及到如何在DataGrid的单元格或者行中添加图标,以增强数据的可视化...

    DataGrid连接Oracle

    `DataGrid` 是一种常用的用户界面控件,常见于.NET Framework或WPF(Windows Presentation Foundation)环境中,用于展示和操作表格数据。它允许用户直观地查看、编辑和管理数据集,提供了丰富的功能,如排序、分组...

    DataGrid控件用法详解

    DataGrid控件的数据源可以是各种类型,最常见的是数据库记录集。通过绑定到CRecordset或CRecordView对象,DataGrid能自动将数据集中的字段映射到控件的列。数据绑定过程通常包括设置控件的DataSource属性,指定数据...

    datagrid copy & paste

    9. **错误处理和边界情况**: 考虑到可能出现的错误情况,如无效的剪贴板数据、超出数据模型范围的粘贴位置,或者在只读模式下的尝试复制和粘贴,都需要有适当的错误处理机制。 10. **跨平台和框架兼容性**: 如果...

    DataGrid_To_Excel

    而将DataGrid中的数据导出为Excel格式的需求很常见,这使得用户能够方便地进行数据分析、编辑或共享。 描述“DataGrid_To_Excel_src”暗示我们可能拥有一个源代码项目,这个项目专门处理DataGrid控件的数据,并将其...

    datagrid技巧大全

    在IT行业中,`datagrid`是一种常见的数据展示控件,尤其在Java开发中,它被广泛应用于数据密集型应用,如数据库记录的查看、编辑和管理。`datagrid`提供了灵活的数据展示方式,允许用户以表格的形式浏览和操作大量...

    ADODC+Datagrid操作实例

    查询数据库是最常见的操作。可以使用ADODC的Command对象来构造SELECT语句,根据条件筛选数据。例如,"SELECT * FROM 表名 WHERE 条件"。执行此命令后,Datagrid会显示匹配的记录。 在实际项目中,我们还需要处理...

    vb DataGrid导出excel例子

    而将DataGrid中的数据导出到Excel是常见的需求,尤其在数据处理和报表生成的场景中。本例提供的"vb DataGrid导出excel例子"是一个很好的学习资源,它将展示如何在VB中实现这个功能,使得开发人员能够快速地将用户...

    flex datagrid 嵌套checkbox实现全选

    这在需要用户批量选择或操作数据的场景中非常常见。以下是对这个主题的详细讲解: 1. **Flex DataGrid组件**: Flex DataGrid是Adobe Flex框架中的一个组件,用于显示结构化的数据集。它可以自动生成列,并根据...

    VB 用datagrid显示数据库信息

    综上所述,VB中使用DataGrid和Adodc的组合是一种常见且实用的方法来显示和操作数据库中的数据。通过熟练掌握这两个控件的使用,你可以创建功能丰富的数据库应用,满足用户的浏览、查询和编辑需求。在提供的压缩包...

    wpf通过datagrid操作数据库

    在WPF中,可以使用IDataErrorInfo接口或ValidationRules类来定义验证规则,并在用户尝试保存更改时显示错误提示。 10. **异步操作**: 考虑到用户体验,数据库操作应尽可能在后台线程执行。WPF提供了...

    DateField与DataGrid的交互

    接着,`DataGrid` 是一种常见的数据展示工具,它可以显示多个字段的数据行,并支持排序、筛选、分页等功能。在 `DataGrid` 中,每一行代表一个数据记录,每一列对应一个字段。通过绑定数据源,`DataGrid` 可以实时...

    WPF DATAGRID全选全不选

    **WPF DATAGRID全选全不选**是Windows Presentation Foundation (WPF)框架中一个常见的功能需求,特别是在数据展示和操作的场景下。在WPF的DataGrid控件中,用户可能希望实现一键全选或一键全不选所有显示的数据行。...

    datagrid-detailview

    在IT行业中,datagrid-detailview是一种常见的前端数据展示和编辑组件,尤其在基于easyUI的Web应用开发中。这个组件主要用于创建具有展开行功能的表格,以便用户能够查看或编辑每行数据的详细信息。在本场景中,...

    WPF中DataGrid导出Excel和Word示例源码

    在实际项目中,可能还需要处理如错误处理、用户界面反馈、多线程优化等问题,以提供更好的用户体验。 在提供的压缩包文件中,"DataGrid导入Office"可能包含了实现这些功能的示例代码和资源。通过研究这些代码,你...

    利用ADO和DATAGRID及HFLEXGRID方法对ACCESS进行操作

    在Microsoft Foundation Classes (MFC)框架中,对ACCESS数据库的操作是一项常见的任务,特别是在开发桌面应用程序时。本主题将深入探讨如何使用ADO(ActiveX Data Objects)、DATAGRID和HFLEXGRID控件来实现这一目标...

    datagrid 多表头 排序 合计

    在IT领域,特别是软件开发中,`datagrid`是一种常见的组件,用于展示数据表格。它允许用户以直观的方式查看和操作大量结构化的数据。在本话题中,我们将详细探讨`datagrid`如何实现多表头、排序以及合计功能,并结合...

    asp.net 将DataGrid数据写入Excel文件.rar

    在ASP.NET开发中,将DataGrid控件中的数据显示在Excel文件中是一项常见的需求,这主要应用于数据导出、报表生成或者数据分析场景。本教程将详细讲解如何实现这一功能。 首先,我们需要了解DataGrid控件。ASP.NET中...

Global site tag (gtag.js) - Google Analytics