当你使用GridView的时候,不要在page_load中绑定数据

在csdn我看到的一个很普遍的编程错误,就是在使用GridView时在page_load中从后台(数据库)绑定数据。实际上,那种写法是asp.net1.1时代我们不太懂asp.net,并且使用DataGrid等比较简单的控件时遗留的一种非常不成熟的写法,没想到现在在很多使用GridView编程的“范例”代码中还不断地影响初学者。这个写法错误地在每一次回发时在page_load中绑定数据,而这个方法中实际上应该是创建上一个页面输出html时的GridView控件树结构,而并不是应该去根据当前后台数据库的最新数据去创建GridView的控件树结构。因此,在page_load中绑定数据不但是大大降低程序运行效率的(因为重复读取后台数据),而且还有逻辑错误。如果要手写绑定代码,那么所有在回发后的绑定功能也应该是在page_load结束之后的某个事件中,而不应该在page_load中。

虽然我使用数据源控件,无需手写相关代码,因此可以确保流程正确。但是,为了给不使用数据源控件绑定数据而是手写代码像GridView.DataSource属性传递数据的做法写一个Demo,我写了一个简化了的程序。(这里使用了.net2008的功能)


首先,在你的网站下创建一个cs文件来提供测试数据:
C# code
   
   
using System.Collections.Generic; using System.Linq; static public class BLL { private static List < TestType > ret; static public IEnumerable < TestType > GetDatas( string cond1, string cond2) { if (ret == null ) { ret = new List < TestType > (); for ( int i = 0 ; i < 10 ; i ++ ) { TestType x = new TestType { 申请人名 = " 王海波 " + i.ToString(), 审核人名 = "" , 审核意见 = "" }; ret.Add(x); } } var result = ret.Where(c => true ); if (cond1 != string .Empty) result = result.Where(c => c.审核意见.Contains(cond1)); if (cond2 != string .Empty) result = result.Where(c => c.审核人名 == cond2); return result; } static public void UpdateRet( string name, string a, string b) { TestType line = ret.Where(x => x.申请人名 == name).FirstOrDefault(); if (line != null ) { line.审核意见 = a; line.审核人名 = b; } } } public class TestType { public string 申请人名 { get ; set ; } public string 审核意见 { get ; set ; } public string 审核人名 { get ; set ; } }


这里,业务对象是由TestType来简单定义的。BLL类有两个方法,用来查询和更新数据。我使用一个 List <TestType> 类型的静态数据集合来保存演示测试数据。实际使用时则往往只要将方法改为对后台数据库操作即可,接口时一样的。


而一个处理界面的aspx内容如下:
HTML code
   
   
<% @ Page Language = " C# " %> < script runat ="server" > protected void Page_Load(object sender, EventArgs e) { if ( ! IsPostBack) this .GridView1.DataBind(); } protected void GridView1_DataBinding(object sender, EventArgs e) { this .GridView1.DataSource = BLL.GetDatas( this .TextBox1.Text.Trim(), this .TextBox2.Text.Trim()); } protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e) { this .GridView1.EditIndex = e.NewEditIndex; this .GridView1.DataBind(); } protected void GridView1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e) { this .GridView1.EditIndex = - 1 ; this .GridView1.DataBind(); } protected void Button1_Click(object sender, EventArgs e) { this .GridView1.DataBind(); } protected void 更新这一行(object sender, EventArgs e) { var bt = sender as LinkButton; var a = (bt.FindControl( " Label1 " ) as Label).Text; var b = (bt.FindControl( " TextBox1 " ) as TextBox).Text; var c = (bt.FindControl( " TextBox2 " ) as TextBox).Text; BLL.UpdateRet(a, b, c); this .GridView1.EditIndex = - 1 ; this .GridView1.DataBind(); } private string[] _审核意见 = null ; public string[] 审核意见 { get { if (_审核意见 == null ) _审核意见 = new string[] { "" , " 同意 " , " 不同意 " , " 发回重审 " }; return _审核意见; } } protected void 选择审核意见(object sender, EventArgs e) { var list = sender as DropDownList; var tb = list.FindControl( " TextBox1 " ) as TextBox; tb.Text = list.SelectedValue; } </ script > <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > < html xmlns ="http://www.w3.org/1999/xhtml" > < head runat ="server" > < title ></ title > </ head > < body > < form id ="form1" runat ="server" > 审核意见: < asp:TextBox ID ="TextBox1" runat ="server" ></ asp:TextBox > < br /> 审核人: < asp:TextBox ID ="TextBox2" runat ="server" ></ asp:TextBox > < br /> < asp:Button ID ="Button1" runat ="server" Text ="重新查询" OnClick ="Button1_Click" /> < br /> < br /> < asp:GridView ID ="GridView1" runat ="server" AutoGenerateColumns ="False" OnDataBinding ="GridView1_DataBinding" OnRowCancelingEdit ="GridView1_RowCancelingEdit" OnRowEditing ="GridView1_RowEditing" > < Columns > < asp:TemplateField HeaderText ="申请人姓名" SortExpression ="申请人名" > < EditItemTemplate > < asp:Label ID ="Label1" runat ="server" Text ='<%# Eval("申请人名") % > '> </ asp:Label > </ EditItemTemplate > < ItemTemplate > < asp:Label ID ="Label1" runat ="server" Text ='<%# Bind("申请人名") % > '> </ asp:Label > </ ItemTemplate > </ asp:TemplateField > < asp:TemplateField HeaderText ="审核意见" SortExpression ="审核意见" > < EditItemTemplate > < asp:TextBox ID ="TextBox1" runat ="server" Text ='<%# Bind("审核意见") % > '> </ asp:TextBox > < asp:DropDownList ID ="DropDownList1" runat ="server" DataSource ="<%# this.审核意见 %>" AutoPostBack ="true" OnSelectedIndexChanged ="选择审核意见" > </ asp:DropDownList > </ EditItemTemplate > < ItemTemplate > < asp:Label ID ="Label2" runat ="server" Text ='<%# Bind("审核意见") % > '> </ asp:Label > </ ItemTemplate > </ asp:TemplateField > < asp:TemplateField HeaderText ="审核人名" SortExpression ="审核人名" > < EditItemTemplate > < asp:TextBox ID ="TextBox2" runat ="server" Text ='<%# Bind("审核人名") % > '> </ asp:TextBox > </ EditItemTemplate > < ItemTemplate > < asp:Label ID ="Label3" runat ="server" Text ='<%# Bind("审核人名") % > '> </ asp:Label > </ ItemTemplate > </ asp:TemplateField > < asp:TemplateField ShowHeader ="False" > < EditItemTemplate > < asp:LinkButton ID ="LinkButton1" runat ="server" CausesValidation ="True" Text ="更新" OnClick ="更新这一行" ></ asp:LinkButton > &nbsp; < asp:LinkButton ID ="LinkButton2" runat ="server" CausesValidation ="False" CommandName ="Cancel" Text ="取消" ></ asp:LinkButton > </ EditItemTemplate > < ItemTemplate > < asp:LinkButton ID ="LinkButton1" runat ="server" CausesValidation ="False" CommandName ="Edit" Text ="编辑" ></ asp:LinkButton > </ ItemTemplate > </ asp:TemplateField > </ Columns > </ asp:GridView > < br /> < asp:Button ID ="Button2" runat ="server" Text ="什么也不做,专用来测试随机回发时页面状态是否正常" /> </ form > </ body > </ html >



在界面中,有两个查询条件,第一个用于输入过滤审核意见(包含某些文字),第二个用来过滤审核人姓名。

请注意,数据时如何、合适绑定的。如果你在 BLL.GetDatas 方法设置一个断点,观察一下,何时才会读取后台数据库值。例如,你可以对某一行,点击“编辑”,然后再DropdownList上选择某个一个审批意见,然后再点击页面最底部的“什么也不做,专用来测试随机回发”按钮,你会看到DroopdownList中的值的状态并不会丢失,而且此时 BLL.GetDatas 中的断点也不会执行(说明并不读取后台数据库值),而且你在“审核意见”的get方法的第一行设置断点调试可以看到此时并不会重新读取DropdownList的后台数据(这说明每一行中某列嵌入复杂控件此时也不会重新绑定)。

而开头说的那种错误写法,则是大量地重复读取后台数据用于重新绑定,不但速度及其慢,而且逻辑上也是有bug的(只是你在开发用的机器上没有什么并发操作,很难发现bug)。

实际上,我看到很多在page_load中有为GridView的DataSource设置从后台查询的数据集来绑定控件做法,不但初学者会如此,写“范例”代码的blog中也会有很多。这是一个相当普遍的编程错误。

 

 

  protected void Page_Load(object sender, EventArgs e)
    {
       
if (!IsPostBack)
           
this.GridView1.DataBind();
    }



这个写法其实是我们的一个懒习惯。按照逻辑,此时放在PreRender中其实是更加合适的,既:

C# code
   
   
protected void Page_PreRender( object sender, EventArgs e) { if ( ! IsPostBack) this .GridView1.DataBind(); }



只是因为页面一创建,就有这个方法写好了,所以我们习惯上随便把代码塞在这个方法里。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值